@xstate-devtools/adapter 0.1.4 → 0.1.6
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 +22 -1
- package/dist/chunk-M4XORXVP.js +307 -0
- package/dist/chunk-M4XORXVP.js.map +1 -0
- package/dist/chunk-W5QGSHOC.js +34 -0
- package/dist/chunk-W5QGSHOC.js.map +1 -0
- package/dist/index.cjs +177 -571
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -10
- package/dist/index.d.ts +2 -10
- package/dist/index.js +2 -2
- package/dist/react.cjs +232 -590
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +31 -5
- package/dist/react.d.ts +31 -5
- package/dist/react.js +61 -13
- package/dist/react.js.map +1 -1
- package/dist/server.cjs +245 -681
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +10 -7
- package/dist/server.d.ts +10 -7
- package/dist/server.js +75 -146
- package/dist/server.js.map +1 -1
- package/package.json +13 -4
- package/dist/chunk-3GM2SFT4.js +0 -680
- package/dist/chunk-3GM2SFT4.js.map +0 -1
- package/dist/chunk-MHHRMHW5.js +0 -62
- package/dist/chunk-MHHRMHW5.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -24,113 +24,19 @@ __export(index_exports, {
|
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(index_exports);
|
|
26
26
|
|
|
27
|
-
// src/logging.ts
|
|
28
|
-
function hasProcessEnv() {
|
|
29
|
-
return typeof process !== "undefined" && typeof process.env !== "undefined";
|
|
30
|
-
}
|
|
31
|
-
function isLoggingEnabled() {
|
|
32
|
-
if (globalThis.__XSTATE_DEVTOOLS_LOGGING__ === true) return true;
|
|
33
|
-
if (!hasProcessEnv()) return false;
|
|
34
|
-
const value = process.env.XSTATE_DEVTOOLS_LOGGING;
|
|
35
|
-
return value === "1" || value === "true";
|
|
36
|
-
}
|
|
37
|
-
function log(level, scope, message, details) {
|
|
38
|
-
if (!isLoggingEnabled()) return;
|
|
39
|
-
if (details === void 0) {
|
|
40
|
-
console[level](`[xstate-devtools:${scope}] ${message}`);
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
console[level](`[xstate-devtools:${scope}] ${message}`, details);
|
|
44
|
-
}
|
|
45
|
-
function debugLog(scope, message, details) {
|
|
46
|
-
log("debug", scope, message, details);
|
|
47
|
-
}
|
|
48
|
-
function infoLog(scope, message, details) {
|
|
49
|
-
log("info", scope, message, details);
|
|
50
|
-
}
|
|
51
|
-
function warnLog(scope, message, details) {
|
|
52
|
-
log("warn", scope, message, details);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// src/sanitize.ts
|
|
56
|
-
var MAX_DEPTH = 10;
|
|
57
|
-
var MAX_STRING_LENGTH = 500;
|
|
58
|
-
var MAX_ARRAY_LENGTH = 100;
|
|
59
|
-
function sanitizeValue(value, depth, seen) {
|
|
60
|
-
if (depth > MAX_DEPTH) return "[MaxDepth]";
|
|
61
|
-
if (value === null || value === void 0) return value;
|
|
62
|
-
if (typeof value === "boolean" || typeof value === "number") return value;
|
|
63
|
-
if (typeof value === "string") {
|
|
64
|
-
return value.length > MAX_STRING_LENGTH ? `${value.slice(0, MAX_STRING_LENGTH)}\u2026` : value;
|
|
65
|
-
}
|
|
66
|
-
if (typeof value === "function") return `[Function: ${value.name || "(anonymous)"}]`;
|
|
67
|
-
if (typeof value === "symbol") return `[Symbol: ${value.description ?? ""}]`;
|
|
68
|
-
if (typeof value === "bigint") return `[BigInt: ${value}]`;
|
|
69
|
-
if (value instanceof Error) return { __type: "Error", name: value.name, message: value.message };
|
|
70
|
-
if (value instanceof Date) return { __type: "Date", iso: value.toISOString() };
|
|
71
|
-
if (value instanceof RegExp) return { __type: "RegExp", source: value.source, flags: value.flags };
|
|
72
|
-
if (typeof value === "object") {
|
|
73
|
-
if (seen.has(value)) return "[Circular]";
|
|
74
|
-
seen.add(value);
|
|
75
|
-
}
|
|
76
|
-
if (value instanceof Map) {
|
|
77
|
-
const entries = [];
|
|
78
|
-
for (const [k, v] of value) {
|
|
79
|
-
if (entries.length >= MAX_ARRAY_LENGTH) break;
|
|
80
|
-
entries.push([sanitizeValue(k, depth + 1, seen), sanitizeValue(v, depth + 1, seen)]);
|
|
81
|
-
}
|
|
82
|
-
return { __type: "Map", entries };
|
|
83
|
-
}
|
|
84
|
-
if (value instanceof Set) {
|
|
85
|
-
const values = [];
|
|
86
|
-
for (const v of value) {
|
|
87
|
-
if (values.length >= MAX_ARRAY_LENGTH) break;
|
|
88
|
-
values.push(sanitizeValue(v, depth + 1, seen));
|
|
89
|
-
}
|
|
90
|
-
return { __type: "Set", values };
|
|
91
|
-
}
|
|
92
|
-
if (value instanceof Promise) return "[Promise]";
|
|
93
|
-
if (value instanceof WeakMap || value instanceof WeakSet) return "[WeakCollection]";
|
|
94
|
-
if (ArrayBuffer.isView(value)) return `[TypedArray: ${value.constructor.name}]`;
|
|
95
|
-
if (typeof Node !== "undefined" && value instanceof Node) {
|
|
96
|
-
return `[DOMNode: ${value.tagName ?? value.nodeName}]`;
|
|
97
|
-
}
|
|
98
|
-
if (Array.isArray(value)) {
|
|
99
|
-
const sliced = value.slice(0, MAX_ARRAY_LENGTH);
|
|
100
|
-
const result = sliced.map((v) => sanitizeValue(v, depth + 1, seen));
|
|
101
|
-
if (value.length > MAX_ARRAY_LENGTH) result.push(`[\u2026${value.length - MAX_ARRAY_LENGTH} more]`);
|
|
102
|
-
return result;
|
|
103
|
-
}
|
|
104
|
-
if (typeof value === "object") {
|
|
105
|
-
const result = {};
|
|
106
|
-
let count = 0;
|
|
107
|
-
for (const [k, v] of Object.entries(value)) {
|
|
108
|
-
if (count++ >= MAX_ARRAY_LENGTH) {
|
|
109
|
-
result["\u2026"] = "[truncated]";
|
|
110
|
-
break;
|
|
111
|
-
}
|
|
112
|
-
result[k] = sanitizeValue(v, depth + 1, seen);
|
|
113
|
-
}
|
|
114
|
-
return result;
|
|
115
|
-
}
|
|
116
|
-
return String(value);
|
|
117
|
-
}
|
|
118
|
-
function sanitize(value, depth = 0) {
|
|
119
|
-
return sanitizeValue(value, depth, /* @__PURE__ */ new WeakSet());
|
|
120
|
-
}
|
|
121
|
-
|
|
122
27
|
// src/serialize.ts
|
|
123
|
-
var MAX_SERIALIZED_NODES = 500;
|
|
124
|
-
var MAX_TRANSITIONS_PER_NODE = 100;
|
|
125
|
-
var MAX_CHILD_STATES = 100;
|
|
126
|
-
var MAX_ACTIONS_PER_TRANSITION = 20;
|
|
127
|
-
var MAX_ENTRY_EXIT_ACTIONS = 20;
|
|
128
|
-
var MAX_INVOKES_PER_NODE = 20;
|
|
129
28
|
function serializeGuard(guard) {
|
|
130
29
|
if (!guard) return void 0;
|
|
131
30
|
if (typeof guard === "string") return guard;
|
|
132
|
-
if (typeof guard === "function")
|
|
133
|
-
|
|
31
|
+
if (typeof guard === "function") {
|
|
32
|
+
const fn = guard;
|
|
33
|
+
if (Array.isArray(fn.guards) && typeof fn.check === "function") {
|
|
34
|
+
const parts = fn.guards.map((g) => serializeGuard(g) ?? "(inline)");
|
|
35
|
+
return `${fn.name || "(combinator)"}(${parts.join(", ")})`;
|
|
36
|
+
}
|
|
37
|
+
return fn.name || "(inline)";
|
|
38
|
+
}
|
|
39
|
+
if (typeof guard === "object") {
|
|
134
40
|
const g = guard;
|
|
135
41
|
return g.type ?? g.name ?? "(inline)";
|
|
136
42
|
}
|
|
@@ -146,214 +52,133 @@ function serializeAction(action) {
|
|
|
146
52
|
return String(action);
|
|
147
53
|
}
|
|
148
54
|
function serializeTransitionList(transitions) {
|
|
149
|
-
return transitions.
|
|
55
|
+
return transitions.map((t) => ({
|
|
150
56
|
eventType: t.eventType ?? "",
|
|
151
57
|
targets: (t.target ?? []).map((n) => n?.id ?? String(n)).filter(Boolean),
|
|
152
58
|
guard: serializeGuard(t.guard),
|
|
153
|
-
actions: (t.actions ?? []).
|
|
59
|
+
actions: (t.actions ?? []).map(serializeAction).filter(Boolean)
|
|
154
60
|
}));
|
|
155
61
|
}
|
|
156
62
|
function serializeInvokes(node) {
|
|
157
|
-
return node.invoke.
|
|
63
|
+
return node.invoke.map((inv) => ({
|
|
158
64
|
id: inv.id ?? "(unknown)",
|
|
159
65
|
src: typeof inv.src === "string" ? inv.src : inv.src?.id ?? inv.src?.name ?? "(inline)"
|
|
160
66
|
}));
|
|
161
67
|
}
|
|
162
|
-
function serializeNode(node
|
|
163
|
-
if (!node || typeof node !== "object") {
|
|
164
|
-
return {
|
|
165
|
-
id: "(unknown)",
|
|
166
|
-
key: "(unknown)",
|
|
167
|
-
type: "atomic",
|
|
168
|
-
states: {},
|
|
169
|
-
on: [],
|
|
170
|
-
always: [],
|
|
171
|
-
entry: [],
|
|
172
|
-
exit: [],
|
|
173
|
-
invoke: []
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
if (state.count >= MAX_SERIALIZED_NODES) {
|
|
177
|
-
return {
|
|
178
|
-
id: node.id ?? "(truncated)",
|
|
179
|
-
key: node.key ?? "(truncated)",
|
|
180
|
-
type: node.type ?? "atomic",
|
|
181
|
-
states: {},
|
|
182
|
-
on: [],
|
|
183
|
-
always: [],
|
|
184
|
-
entry: [],
|
|
185
|
-
exit: [],
|
|
186
|
-
invoke: []
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
if (state.seen.has(node)) {
|
|
190
|
-
return {
|
|
191
|
-
id: node.id ?? "(circular)",
|
|
192
|
-
key: node.key ?? "(circular)",
|
|
193
|
-
type: node.type ?? "atomic",
|
|
194
|
-
states: {},
|
|
195
|
-
on: [],
|
|
196
|
-
always: [],
|
|
197
|
-
entry: [],
|
|
198
|
-
exit: [],
|
|
199
|
-
invoke: []
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
state.seen.add(node);
|
|
203
|
-
state.count += 1;
|
|
68
|
+
function serializeNode(node) {
|
|
204
69
|
const allTransitions = [];
|
|
205
70
|
if (node.transitions instanceof Map) {
|
|
206
71
|
for (const [, tList] of node.transitions) {
|
|
207
|
-
if (allTransitions.length >= MAX_TRANSITIONS_PER_NODE) break;
|
|
208
72
|
allTransitions.push(...serializeTransitionList(tList));
|
|
209
|
-
if (allTransitions.length >= MAX_TRANSITIONS_PER_NODE) {
|
|
210
|
-
allTransitions.length = MAX_TRANSITIONS_PER_NODE;
|
|
211
|
-
break;
|
|
212
|
-
}
|
|
213
73
|
}
|
|
214
74
|
}
|
|
215
75
|
const always = Array.isArray(node.always) ? serializeTransitionList(node.always) : [];
|
|
216
|
-
const childEntries = Object.entries(node.states ?? {}).slice(0, MAX_CHILD_STATES);
|
|
217
76
|
return {
|
|
218
77
|
id: node.id,
|
|
219
78
|
key: node.key,
|
|
220
79
|
type: node.type,
|
|
221
80
|
initial: node.initial?.target?.[0]?.key,
|
|
222
|
-
states: Object.fromEntries(
|
|
81
|
+
states: Object.fromEntries(
|
|
82
|
+
Object.entries(node.states ?? {}).map(([k, v]) => [k, serializeNode(v)])
|
|
83
|
+
),
|
|
223
84
|
on: allTransitions,
|
|
224
85
|
always,
|
|
225
|
-
entry: (node.entry ?? []).
|
|
226
|
-
exit: (node.exit ?? []).
|
|
227
|
-
invoke: serializeInvokes(node)
|
|
228
|
-
sourceLocation: node.config?.__xstateDevtoolsSource ?? void 0,
|
|
229
|
-
description: node.config?.description ?? void 0
|
|
86
|
+
entry: (node.entry ?? []).map(serializeAction).filter(Boolean),
|
|
87
|
+
exit: (node.exit ?? []).map(serializeAction).filter(Boolean),
|
|
88
|
+
invoke: serializeInvokes(node)
|
|
230
89
|
};
|
|
231
90
|
}
|
|
232
91
|
function serializeMachine(machine, sourceLocation) {
|
|
233
92
|
return {
|
|
234
93
|
id: machine.id,
|
|
235
|
-
root: serializeNode(machine.root
|
|
94
|
+
root: serializeNode(machine.root),
|
|
236
95
|
sourceLocation
|
|
237
96
|
};
|
|
238
97
|
}
|
|
239
98
|
|
|
240
|
-
// src/
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
99
|
+
// src/sanitize.ts
|
|
100
|
+
var MAX_DEPTH = 10;
|
|
101
|
+
var MAX_STRING_LENGTH = 500;
|
|
102
|
+
var MAX_ARRAY_LENGTH = 100;
|
|
103
|
+
var MAX_NODES = 1e4;
|
|
104
|
+
function sanitizeInner(value, ctx) {
|
|
105
|
+
if (ctx.depth > MAX_DEPTH) return "[MaxDepth]";
|
|
106
|
+
if (++ctx.budget.n > MAX_NODES) return "[Truncated]";
|
|
107
|
+
if (value === null || value === void 0) return value;
|
|
108
|
+
if (typeof value === "boolean" || typeof value === "number") return value;
|
|
109
|
+
if (typeof value === "string") {
|
|
110
|
+
return value.length > MAX_STRING_LENGTH ? value.slice(0, MAX_STRING_LENGTH) + "\u2026" : value;
|
|
247
111
|
}
|
|
248
|
-
if ("
|
|
249
|
-
if ("
|
|
250
|
-
if (
|
|
251
|
-
|
|
112
|
+
if (typeof value === "function") return `[Function: ${value.name || "(anonymous)"}]`;
|
|
113
|
+
if (typeof value === "symbol") return `[Symbol: ${value.description ?? ""}]`;
|
|
114
|
+
if (typeof value === "bigint") return `[BigInt: ${value}]`;
|
|
115
|
+
if (value instanceof Error) return { __type: "Error", name: value.name, message: value.message };
|
|
116
|
+
if (value instanceof Date) return { __type: "Date", iso: value.toISOString() };
|
|
117
|
+
if (value instanceof RegExp) return { __type: "RegExp", source: value.source, flags: value.flags };
|
|
118
|
+
if (value instanceof Promise) return "[Promise]";
|
|
119
|
+
if (value instanceof WeakMap || value instanceof WeakSet) return "[WeakCollection]";
|
|
120
|
+
if (ArrayBuffer.isView(value)) return `[TypedArray: ${value.constructor.name}]`;
|
|
121
|
+
if (typeof Node !== "undefined" && value instanceof Node) {
|
|
122
|
+
return `[DOMNode: ${value.tagName ?? value.nodeName}]`;
|
|
252
123
|
}
|
|
253
|
-
return
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
warnLog(`${source}:adapter`, message, details);
|
|
270
|
-
}
|
|
271
|
-
function isLibraryStackFrame(line) {
|
|
272
|
-
const normalized = line.replace(/\\/g, "/").toLowerCase();
|
|
273
|
-
return normalized.includes("/node_modules/xstate/") || normalized.includes("/node_modules/@xstate/") || normalized.includes("/@xstate-devtools/adapter/") || normalized.includes("/packages/adapter/");
|
|
274
|
-
}
|
|
275
|
-
function normalizeStackFrame(line) {
|
|
276
|
-
return line.trim().replace(/^at\s+/, "");
|
|
277
|
-
}
|
|
278
|
-
function extractStackFrameLocation(frame) {
|
|
279
|
-
return frame.match(/\((.*)\)$/)?.[1] ?? frame;
|
|
280
|
-
}
|
|
281
|
-
function isAnonymousOrEvalLocation(location) {
|
|
282
|
-
const normalized = location.trim().toLowerCase().replace(/^[./\\]+/, "");
|
|
283
|
-
return normalized === "<anonymous>" || normalized === "anonymous" || normalized === "(anonymous)" || normalized === "eval" || normalized === "<eval>" || normalized === "[native code]";
|
|
284
|
-
}
|
|
285
|
-
function hasFilesystemBackedPath(location) {
|
|
286
|
-
const trimmed = location.trim();
|
|
287
|
-
if (!trimmed) return false;
|
|
288
|
-
const match = trimmed.match(/^(.*?)(?::\d+)?(?::\d+)?$/);
|
|
289
|
-
const rawPath = (match?.[1] ?? trimmed).trim();
|
|
290
|
-
if (!rawPath || isAnonymousOrEvalLocation(rawPath)) return false;
|
|
291
|
-
if (/^[a-zA-Z]:[\\/]/.test(rawPath)) return true;
|
|
292
|
-
if (rawPath.startsWith("/") || rawPath.startsWith("./") || rawPath.startsWith("../")) return true;
|
|
293
|
-
if (/^[a-zA-Z][a-zA-Z\d+.-]*:\/\//.test(rawPath)) {
|
|
294
|
-
try {
|
|
295
|
-
const url = new URL(rawPath);
|
|
296
|
-
if (url.protocol === "file:") return true;
|
|
297
|
-
return url.pathname.startsWith("/@fs/");
|
|
298
|
-
} catch {
|
|
299
|
-
return false;
|
|
124
|
+
if (ctx.seen.has(value)) return "[Circular]";
|
|
125
|
+
ctx.seen.add(value);
|
|
126
|
+
const child = { ...ctx, depth: ctx.depth + 1 };
|
|
127
|
+
if (value instanceof Map) {
|
|
128
|
+
const entries = [];
|
|
129
|
+
for (const [k, v] of value) {
|
|
130
|
+
if (entries.length >= MAX_ARRAY_LENGTH) break;
|
|
131
|
+
entries.push([sanitizeInner(k, child), sanitizeInner(v, child)]);
|
|
132
|
+
}
|
|
133
|
+
return { __type: "Map", entries };
|
|
134
|
+
}
|
|
135
|
+
if (value instanceof Set) {
|
|
136
|
+
const values = [];
|
|
137
|
+
for (const v of value) {
|
|
138
|
+
if (values.length >= MAX_ARRAY_LENGTH) break;
|
|
139
|
+
values.push(sanitizeInner(v, child));
|
|
300
140
|
}
|
|
141
|
+
return { __type: "Set", values };
|
|
301
142
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
if (!match) return location;
|
|
308
|
-
const [, rawPath, line, column] = match;
|
|
309
|
-
if (!rawPath || !/^https?:\/\//.test(rawPath)) return location;
|
|
310
|
-
try {
|
|
311
|
-
const url = new URL(rawPath);
|
|
312
|
-
const pathname = decodeURIComponent(url.pathname);
|
|
313
|
-
if (!pathname.startsWith("/app/")) return location;
|
|
314
|
-
const root = options.webSourceRoot.replace(/\/+$/, "");
|
|
315
|
-
const filePath = `${root}${pathname}`;
|
|
316
|
-
const suffix = line ? `:${line}${column ? `:${column}` : ""}` : "";
|
|
317
|
-
return `${filePath}${suffix}`;
|
|
318
|
-
} catch {
|
|
319
|
-
return location;
|
|
143
|
+
if (Array.isArray(value)) {
|
|
144
|
+
const sliced = value.slice(0, MAX_ARRAY_LENGTH);
|
|
145
|
+
const result = sliced.map((v) => sanitizeInner(v, child));
|
|
146
|
+
if (value.length > MAX_ARRAY_LENGTH) result.push(`[\u2026${value.length - MAX_ARRAY_LENGTH} more]`);
|
|
147
|
+
return result;
|
|
320
148
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
extractStackFrameLocation(normalizedFrame),
|
|
331
|
-
source,
|
|
332
|
-
options
|
|
333
|
-
);
|
|
334
|
-
if (!hasFilesystemBackedPath(location)) continue;
|
|
335
|
-
const wrapped = normalizedFrame.match(/\((.*)\)$/);
|
|
336
|
-
if (wrapped) {
|
|
337
|
-
return normalizedFrame.replace(wrapped[1], location);
|
|
149
|
+
if (typeof value === "object") {
|
|
150
|
+
const result = {};
|
|
151
|
+
let count = 0;
|
|
152
|
+
for (const [k, v] of Object.entries(value)) {
|
|
153
|
+
if (count++ >= MAX_ARRAY_LENGTH) {
|
|
154
|
+
result["\u2026"] = "[truncated]";
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
result[k] = sanitizeInner(v, child);
|
|
338
158
|
}
|
|
339
|
-
return
|
|
159
|
+
return result;
|
|
340
160
|
}
|
|
341
|
-
return
|
|
161
|
+
return String(value);
|
|
162
|
+
}
|
|
163
|
+
function sanitize(value) {
|
|
164
|
+
return sanitizeInner(value, { depth: 0, budget: { n: 0 }, seen: /* @__PURE__ */ new WeakSet() });
|
|
342
165
|
}
|
|
343
|
-
|
|
166
|
+
|
|
167
|
+
// src/core.ts
|
|
168
|
+
function getSourceLocation() {
|
|
344
169
|
try {
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
return
|
|
170
|
+
const lines = new Error().stack?.split("\n") ?? [];
|
|
171
|
+
const callerLine = lines.find(
|
|
172
|
+
(l, i) => i > 3 && !l.includes("xstate") && !l.includes("adapter")
|
|
173
|
+
);
|
|
174
|
+
return callerLine?.trim().replace(/^at\s+/, "");
|
|
350
175
|
} catch {
|
|
351
176
|
return void 0;
|
|
352
177
|
}
|
|
353
178
|
}
|
|
354
179
|
function serializeSnapshot(snapshot) {
|
|
355
180
|
return {
|
|
356
|
-
value: snapshot?.value ?? null,
|
|
181
|
+
value: sanitize(snapshot?.value ?? null),
|
|
357
182
|
context: sanitize(snapshot?.context),
|
|
358
183
|
status: snapshot?.status ?? "active",
|
|
359
184
|
error: snapshot?.error ? sanitize(snapshot.error) : void 0
|
|
@@ -366,125 +191,18 @@ function safeSerializeSnapshot(actorRef) {
|
|
|
366
191
|
return { value: null, context: void 0, status: "active" };
|
|
367
192
|
}
|
|
368
193
|
}
|
|
369
|
-
function
|
|
370
|
-
const
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
if (typeof actor.logic?.id === "string" && actor.logic.id.length > 0) return actor.logic.id;
|
|
374
|
-
if (typeof actor.logic?.name === "string" && actor.logic.name.length > 0) return actor.logic.name;
|
|
375
|
-
if (src && typeof src === "object") {
|
|
376
|
-
const namedSrc = src;
|
|
377
|
-
if (typeof namedSrc.id === "string" && namedSrc.id.length > 0) return namedSrc.id;
|
|
378
|
-
if (typeof namedSrc.name === "string" && namedSrc.name.length > 0) return namedSrc.name;
|
|
379
|
-
}
|
|
380
|
-
return void 0;
|
|
381
|
-
}
|
|
382
|
-
function getNodeInitialChild(node) {
|
|
383
|
-
if (!node.states) return null;
|
|
384
|
-
if (typeof node.initial === "string") {
|
|
385
|
-
return node.states[node.initial] ?? null;
|
|
386
|
-
}
|
|
387
|
-
const target = Array.isArray(node.initial?.target) ? node.initial.target[0] : null;
|
|
388
|
-
return target ?? null;
|
|
389
|
-
}
|
|
390
|
-
function encodeChildValue(child, childValue) {
|
|
391
|
-
if (child.type === "atomic" || child.type === "final" || child.type === "history") {
|
|
392
|
-
return child.key;
|
|
393
|
-
}
|
|
394
|
-
return { [child.key]: childValue };
|
|
395
|
-
}
|
|
396
|
-
function getDefaultStateValue(node) {
|
|
397
|
-
if (node.type === "parallel") {
|
|
398
|
-
const value = {};
|
|
399
|
-
for (const child of Object.values(node.states ?? {})) {
|
|
400
|
-
value[child.key] = getDefaultSelectionValue(child);
|
|
401
|
-
}
|
|
402
|
-
return value;
|
|
403
|
-
}
|
|
404
|
-
const initialChild = getNodeInitialChild(node);
|
|
405
|
-
if (!initialChild) return {};
|
|
406
|
-
return encodeChildValue(initialChild, getDefaultStateValue(initialChild));
|
|
407
|
-
}
|
|
408
|
-
function getDefaultSelectionValue(node) {
|
|
409
|
-
if (node.type === "atomic" || node.type === "final" || node.type === "history") {
|
|
410
|
-
return node.key;
|
|
411
|
-
}
|
|
412
|
-
return getDefaultStateValue(node);
|
|
413
|
-
}
|
|
414
|
-
function getExistingChildValue(value, childKey) {
|
|
415
|
-
if (!value || typeof value !== "object") return void 0;
|
|
416
|
-
return value[childKey];
|
|
417
|
-
}
|
|
418
|
-
function getPathToRoot(target, root) {
|
|
419
|
-
const path = [];
|
|
420
|
-
let current = target;
|
|
421
|
-
while (current) {
|
|
422
|
-
path.unshift(current);
|
|
423
|
-
if (current.id === root.id) return path;
|
|
424
|
-
current = current.parent;
|
|
425
|
-
}
|
|
426
|
-
throw new Error(`State node '${target.id}' is not part of machine '${root.id}'`);
|
|
427
|
-
}
|
|
428
|
-
function buildTargetStateValue(node, path, currentValue) {
|
|
429
|
-
const [, ...restPath] = path;
|
|
430
|
-
if (restPath.length === 0) {
|
|
431
|
-
if (node.type === "parallel") {
|
|
432
|
-
const next = {};
|
|
433
|
-
for (const child2 of Object.values(node.states ?? {})) {
|
|
434
|
-
next[child2.key] = getExistingChildValue(currentValue, child2.key) ?? getDefaultSelectionValue(child2);
|
|
435
|
-
}
|
|
436
|
-
return next;
|
|
437
|
-
}
|
|
438
|
-
if (node.type === "compound") {
|
|
439
|
-
return getDefaultStateValue(node);
|
|
440
|
-
}
|
|
441
|
-
return node.key;
|
|
442
|
-
}
|
|
443
|
-
const child = restPath[0];
|
|
444
|
-
if (node.type === "parallel") {
|
|
445
|
-
const next = {};
|
|
446
|
-
for (const sibling of Object.values(node.states ?? {})) {
|
|
447
|
-
if (sibling.key === child.key) {
|
|
448
|
-
next[sibling.key] = buildTargetStateValue(
|
|
449
|
-
sibling,
|
|
450
|
-
restPath,
|
|
451
|
-
getExistingChildValue(currentValue, sibling.key)
|
|
452
|
-
);
|
|
453
|
-
} else {
|
|
454
|
-
next[sibling.key] = getExistingChildValue(currentValue, sibling.key) ?? getDefaultSelectionValue(sibling);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
return next;
|
|
194
|
+
function safePersistedSnapshot(actorRef) {
|
|
195
|
+
const getPersisted = actorRef.getPersistedSnapshot;
|
|
196
|
+
if (typeof getPersisted !== "function") {
|
|
197
|
+
return { error: "Actor does not support getPersistedSnapshot." };
|
|
458
198
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
)
|
|
464
|
-
|
|
465
|
-
}
|
|
466
|
-
function setActiveState(actorRef, stateNodeId) {
|
|
467
|
-
const mutableActorRef = actorRef;
|
|
468
|
-
const machine = mutableActorRef.logic;
|
|
469
|
-
if (!machine?.getStateNodeById || !machine.resolveState || typeof mutableActorRef.update !== "function") {
|
|
470
|
-
throw new Error("Actor does not expose machine state mutation internals");
|
|
199
|
+
try {
|
|
200
|
+
const raw = getPersisted.call(actorRef);
|
|
201
|
+
if (raw === void 0) return { error: "No persisted snapshot available." };
|
|
202
|
+
return { persisted: JSON.parse(JSON.stringify(raw)) };
|
|
203
|
+
} catch (e) {
|
|
204
|
+
return { error: `Snapshot is not JSON-serializable: ${e.message}` };
|
|
471
205
|
}
|
|
472
|
-
const currentSnapshot = actorRef.getSnapshot();
|
|
473
|
-
const targetNode = machine.getStateNodeById(stateNodeId);
|
|
474
|
-
const path = getPathToRoot(targetNode, machine.root);
|
|
475
|
-
const targetValue = buildTargetStateValue(machine.root, path, currentSnapshot?.value);
|
|
476
|
-
const nextSnapshot = machine.resolveState({
|
|
477
|
-
value: targetValue,
|
|
478
|
-
context: currentSnapshot?.context,
|
|
479
|
-
status: currentSnapshot?.status,
|
|
480
|
-
output: currentSnapshot?.output,
|
|
481
|
-
error: currentSnapshot?.error,
|
|
482
|
-
historyValue: currentSnapshot?.historyValue
|
|
483
|
-
});
|
|
484
|
-
mutableActorRef.update(nextSnapshot, {
|
|
485
|
-
type: "xstate.devtools.set-active-state",
|
|
486
|
-
stateNodeId
|
|
487
|
-
});
|
|
488
206
|
}
|
|
489
207
|
var SEQ_KEY = "__xstate_devtools_global_seq__";
|
|
490
208
|
function nextSeq() {
|
|
@@ -494,10 +212,10 @@ function nextSeq() {
|
|
|
494
212
|
g[SEQ_KEY] = next;
|
|
495
213
|
return next;
|
|
496
214
|
}
|
|
497
|
-
function createInspector(transport, source
|
|
215
|
+
function createInspector(transport, source) {
|
|
498
216
|
const actorRefs = /* @__PURE__ */ new Map();
|
|
499
|
-
const
|
|
500
|
-
const prefix =
|
|
217
|
+
const restoreHandlers = /* @__PURE__ */ new Map();
|
|
218
|
+
const prefix = source + ":";
|
|
501
219
|
const tag = (sessionId) => prefix + sessionId;
|
|
502
220
|
const tagOptional = (id) => id ? prefix + id : void 0;
|
|
503
221
|
const stripIfMine = (id) => id.startsWith(prefix) ? id.slice(prefix.length) : null;
|
|
@@ -509,242 +227,130 @@ function createInspector(transport, source, options = {}) {
|
|
|
509
227
|
return;
|
|
510
228
|
}
|
|
511
229
|
if (snap?.status !== "active") {
|
|
512
|
-
|
|
513
|
-
type: "XSTATE_ACTOR_STOPPED",
|
|
514
|
-
sessionId: tag(actorRef.sessionId)
|
|
515
|
-
};
|
|
516
|
-
debugLog2(source, "actor stopped; notifying transport", summarizeMessage(message));
|
|
517
|
-
transport.send(message);
|
|
230
|
+
transport.send({ type: "XSTATE_ACTOR_STOPPED", sessionId: tag(actorRef.sessionId) });
|
|
518
231
|
actorRefs.delete(actorRef.sessionId);
|
|
519
|
-
actorMachines.delete(actorRef.sessionId);
|
|
520
232
|
}
|
|
521
233
|
}
|
|
522
234
|
const unsubscribe = transport.subscribe((message) => {
|
|
523
|
-
debugLog2(source, "received message from transport", summarizeMessage(message));
|
|
524
|
-
if (message.type === "XSTATE_PANEL_CONNECTED") {
|
|
525
|
-
infoLog2(source, "panel connected; resyncing actors", { actorCount: actorRefs.size });
|
|
526
|
-
actorRefs.forEach((actorRef, sessionId) => {
|
|
527
|
-
const machine = actorMachines.get(sessionId) ?? null;
|
|
528
|
-
const resyncMessage = {
|
|
529
|
-
type: "XSTATE_ACTOR_REGISTERED",
|
|
530
|
-
sessionId: tag(sessionId),
|
|
531
|
-
parentSessionId: tagOptional(actorRef._parent?.sessionId),
|
|
532
|
-
displayName: getActorDisplayName(actorRef),
|
|
533
|
-
machine,
|
|
534
|
-
snapshot: safeSerializeSnapshot(actorRef),
|
|
535
|
-
globalSeq: nextSeq(),
|
|
536
|
-
timestamp: Date.now()
|
|
537
|
-
};
|
|
538
|
-
debugLog2(source, "resyncing actor", summarizeMessage(resyncMessage));
|
|
539
|
-
transport.send(resyncMessage);
|
|
540
|
-
});
|
|
541
|
-
return;
|
|
542
|
-
}
|
|
543
235
|
if (message.type === "XSTATE_DISPATCH") {
|
|
544
236
|
const local = stripIfMine(message.sessionId);
|
|
545
|
-
if (local === null)
|
|
546
|
-
debugLog2(source, "ignoring dispatch for different source", summarizeMessage(message));
|
|
547
|
-
return;
|
|
548
|
-
}
|
|
237
|
+
if (local === null) return;
|
|
549
238
|
const ref = actorRefs.get(local);
|
|
550
239
|
if (ref) {
|
|
551
240
|
try {
|
|
552
|
-
debugLog2(source, "dispatching event to actor", {
|
|
553
|
-
sessionId: local,
|
|
554
|
-
eventType: message.event && typeof message.event === "object" && "type" in message.event ? message.event.type : void 0
|
|
555
|
-
});
|
|
556
241
|
ref.send(message.event);
|
|
557
242
|
} catch (e) {
|
|
558
|
-
|
|
243
|
+
console.warn("[xstate-devtools] dispatch error:", e);
|
|
559
244
|
}
|
|
560
|
-
} else {
|
|
561
|
-
warnLog2(source, "received dispatch for unknown actor", {
|
|
562
|
-
sessionId: local,
|
|
563
|
-
knownActors: actorRefs.size
|
|
564
|
-
});
|
|
565
245
|
}
|
|
566
|
-
|
|
567
|
-
}
|
|
568
|
-
if (message.type === "XSTATE_SET_ACTIVE_STATE") {
|
|
246
|
+
} else if (message.type === "XSTATE_REQUEST_PERSISTED") {
|
|
569
247
|
const local = stripIfMine(message.sessionId);
|
|
570
|
-
if (local === null)
|
|
571
|
-
debugLog2(
|
|
572
|
-
source,
|
|
573
|
-
"ignoring state activation for different source",
|
|
574
|
-
summarizeMessage(message)
|
|
575
|
-
);
|
|
576
|
-
return;
|
|
577
|
-
}
|
|
248
|
+
if (local === null) return;
|
|
578
249
|
const ref = actorRefs.get(local);
|
|
579
|
-
if (!ref)
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
250
|
+
if (!ref) return;
|
|
251
|
+
const { persisted, error } = safePersistedSnapshot(ref);
|
|
252
|
+
transport.send({
|
|
253
|
+
type: "XSTATE_PERSISTED_SNAPSHOT",
|
|
254
|
+
sessionId: tag(local),
|
|
255
|
+
persisted,
|
|
256
|
+
error,
|
|
257
|
+
timestamp: Date.now()
|
|
258
|
+
});
|
|
259
|
+
} else if (message.type === "XSTATE_RESTORE") {
|
|
260
|
+
const local = stripIfMine(message.sessionId);
|
|
261
|
+
if (local === null) return;
|
|
262
|
+
const handler = restoreHandlers.get(local);
|
|
263
|
+
if (handler) {
|
|
264
|
+
try {
|
|
265
|
+
handler(message.persisted);
|
|
266
|
+
} catch (e) {
|
|
267
|
+
console.warn("[xstate-devtools] restore error:", e);
|
|
268
|
+
}
|
|
585
269
|
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
const inspect = (inspectionEvent) => {
|
|
273
|
+
try {
|
|
274
|
+
if (inspectionEvent.type === "@xstate.actor") {
|
|
275
|
+
const actorRef = inspectionEvent.actorRef;
|
|
276
|
+
const sessionId = actorRef.sessionId;
|
|
277
|
+
actorRefs.set(sessionId, actorRef);
|
|
278
|
+
const logic = actorRef.logic;
|
|
279
|
+
const machine = logic?.root ? serializeMachine(logic, getSourceLocation()) : null;
|
|
280
|
+
transport.send({
|
|
281
|
+
type: "XSTATE_ACTOR_REGISTERED",
|
|
282
|
+
sessionId: tag(sessionId),
|
|
283
|
+
parentSessionId: tagOptional(actorRef._parent?.sessionId),
|
|
284
|
+
// actorRef.id is the invoke `id` for invoked actors — lets the debugger
|
|
285
|
+
// nest non-machine actors (promise/callback) under their state.
|
|
286
|
+
actorId: actorRef.id,
|
|
287
|
+
machine,
|
|
288
|
+
snapshot: safeSerializeSnapshot(actorRef),
|
|
289
|
+
globalSeq: nextSeq(),
|
|
290
|
+
timestamp: Date.now()
|
|
291
|
+
});
|
|
292
|
+
} else if (inspectionEvent.type === "@xstate.snapshot") {
|
|
293
|
+
transport.send({
|
|
590
294
|
type: "XSTATE_SNAPSHOT",
|
|
591
|
-
sessionId: tag(
|
|
592
|
-
snapshot:
|
|
295
|
+
sessionId: tag(inspectionEvent.actorRef.sessionId),
|
|
296
|
+
snapshot: serializeSnapshot(inspectionEvent.snapshot),
|
|
297
|
+
timestamp: Date.now(),
|
|
298
|
+
globalSeq: nextSeq()
|
|
299
|
+
});
|
|
300
|
+
checkAndNotifyStop(inspectionEvent.actorRef);
|
|
301
|
+
} else if (inspectionEvent.type === "@xstate.event") {
|
|
302
|
+
transport.send({
|
|
303
|
+
type: "XSTATE_EVENT",
|
|
304
|
+
sessionId: tag(inspectionEvent.actorRef.sessionId),
|
|
305
|
+
event: inspectionEvent.event,
|
|
306
|
+
snapshotAfter: safeSerializeSnapshot(inspectionEvent.actorRef),
|
|
593
307
|
timestamp: Date.now(),
|
|
594
308
|
globalSeq: nextSeq()
|
|
595
|
-
};
|
|
596
|
-
debugLog2(
|
|
597
|
-
source,
|
|
598
|
-
"sending snapshot after state activation",
|
|
599
|
-
summarizeMessage(snapshotMessage)
|
|
600
|
-
);
|
|
601
|
-
transport.send(snapshotMessage);
|
|
602
|
-
} catch (error) {
|
|
603
|
-
warnLog2(source, "failed to set active state", {
|
|
604
|
-
error,
|
|
605
|
-
sessionId: local,
|
|
606
|
-
stateNodeId: message.stateNodeId
|
|
607
309
|
});
|
|
310
|
+
checkAndNotifyStop(inspectionEvent.actorRef);
|
|
608
311
|
}
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
transport.send({ type: "XSTATE_ADAPTER_READY" });
|
|
612
|
-
infoLog2(source, "inspector created");
|
|
613
|
-
const inspect = (inspectionEvent) => {
|
|
614
|
-
debugLog2(source, "inspect callback invoked", summarizeInspectionEvent(inspectionEvent));
|
|
615
|
-
if (inspectionEvent.type === "@xstate.actor") {
|
|
616
|
-
const actorRef = inspectionEvent.actorRef;
|
|
617
|
-
const sessionId = actorRef.sessionId;
|
|
618
|
-
const actorLogic = actorRef.logic;
|
|
619
|
-
const machine = actorLogic?.root ? serializeMachine(
|
|
620
|
-
actorLogic,
|
|
621
|
-
actorLogic.config?.__xstateDevtoolsSource ?? getSourceLocation(source, options)
|
|
622
|
-
) : null;
|
|
623
|
-
actorRefs.set(sessionId, actorRef);
|
|
624
|
-
actorMachines.set(sessionId, machine);
|
|
625
|
-
const notifyStop = () => {
|
|
626
|
-
if (actorRefs.has(sessionId)) {
|
|
627
|
-
actorRefs.delete(sessionId);
|
|
628
|
-
actorMachines.delete(sessionId);
|
|
629
|
-
const stopMsg = {
|
|
630
|
-
type: "XSTATE_ACTOR_STOPPED",
|
|
631
|
-
sessionId: tag(sessionId)
|
|
632
|
-
};
|
|
633
|
-
debugLog2(source, "actor stopped; notifying transport", summarizeMessage(stopMsg));
|
|
634
|
-
transport.send(stopMsg);
|
|
635
|
-
}
|
|
636
|
-
};
|
|
637
|
-
try {
|
|
638
|
-
actorRef.subscribe({ complete: notifyStop, error: notifyStop });
|
|
639
|
-
} catch {
|
|
640
|
-
}
|
|
641
|
-
const message = {
|
|
642
|
-
type: "XSTATE_ACTOR_REGISTERED",
|
|
643
|
-
sessionId: tag(sessionId),
|
|
644
|
-
parentSessionId: tagOptional(actorRef._parent?.sessionId),
|
|
645
|
-
displayName: getActorDisplayName(actorRef),
|
|
646
|
-
machine,
|
|
647
|
-
snapshot: safeSerializeSnapshot(actorRef),
|
|
648
|
-
globalSeq: nextSeq(),
|
|
649
|
-
timestamp: Date.now()
|
|
650
|
-
};
|
|
651
|
-
infoLog2(source, "registering actor with transport", {
|
|
652
|
-
message: summarizeMessage(message),
|
|
653
|
-
actorCount: actorRefs.size,
|
|
654
|
-
hasMachine: machine !== null
|
|
655
|
-
});
|
|
656
|
-
transport.send(message);
|
|
657
|
-
} else if (inspectionEvent.type === "@xstate.snapshot") {
|
|
658
|
-
const message = {
|
|
659
|
-
type: "XSTATE_SNAPSHOT",
|
|
660
|
-
sessionId: tag(inspectionEvent.actorRef.sessionId),
|
|
661
|
-
snapshot: serializeSnapshot(inspectionEvent.snapshot),
|
|
662
|
-
timestamp: Date.now(),
|
|
663
|
-
globalSeq: nextSeq()
|
|
664
|
-
};
|
|
665
|
-
debugLog2(source, "sending snapshot to transport", summarizeMessage(message));
|
|
666
|
-
transport.send(message);
|
|
667
|
-
checkAndNotifyStop(inspectionEvent.actorRef);
|
|
668
|
-
} else if (inspectionEvent.type === "@xstate.event") {
|
|
669
|
-
const message = {
|
|
670
|
-
type: "XSTATE_EVENT",
|
|
671
|
-
sessionId: tag(inspectionEvent.actorRef.sessionId),
|
|
672
|
-
// sanitize() returns unknown; the inspected event keeps its { type, ... }
|
|
673
|
-
// shape, so it is a SerializedEvent after deep-sanitizing.
|
|
674
|
-
event: sanitize(inspectionEvent.event),
|
|
675
|
-
snapshotAfter: safeSerializeSnapshot(inspectionEvent.actorRef),
|
|
676
|
-
timestamp: Date.now(),
|
|
677
|
-
globalSeq: nextSeq()
|
|
678
|
-
};
|
|
679
|
-
debugLog2(source, "sending event to transport", summarizeMessage(message));
|
|
680
|
-
transport.send(message);
|
|
681
|
-
checkAndNotifyStop(inspectionEvent.actorRef);
|
|
682
|
-
} else {
|
|
683
|
-
debugLog2(
|
|
684
|
-
source,
|
|
685
|
-
"ignoring unsupported inspection event",
|
|
686
|
-
summarizeInspectionEvent(inspectionEvent)
|
|
687
|
-
);
|
|
312
|
+
} catch (e) {
|
|
313
|
+
console.warn("[xstate-devtools] inspection failed, dropping event:", e.message);
|
|
688
314
|
}
|
|
689
315
|
};
|
|
316
|
+
function registerRestore(sessionId, handler) {
|
|
317
|
+
restoreHandlers.set(sessionId, handler);
|
|
318
|
+
return () => {
|
|
319
|
+
if (restoreHandlers.get(sessionId) === handler) restoreHandlers.delete(sessionId);
|
|
320
|
+
};
|
|
321
|
+
}
|
|
690
322
|
function dispose() {
|
|
691
|
-
infoLog2(source, "disposing inspector", { actorCount: actorRefs.size });
|
|
692
323
|
unsubscribe();
|
|
693
324
|
actorRefs.clear();
|
|
694
|
-
|
|
325
|
+
restoreHandlers.clear();
|
|
695
326
|
}
|
|
696
|
-
return { inspect, dispose };
|
|
327
|
+
return { inspect, dispose, registerRestore };
|
|
697
328
|
}
|
|
698
329
|
|
|
699
330
|
// src/index.ts
|
|
700
|
-
function createAdapter(
|
|
331
|
+
function createAdapter() {
|
|
701
332
|
if (typeof window === "undefined") {
|
|
702
|
-
infoLog("web:adapter", "createAdapter called without window; returning no-op adapter");
|
|
703
333
|
return { inspect: () => {
|
|
704
334
|
}, dispose: () => {
|
|
335
|
+
}, registerRestore: () => () => {
|
|
705
336
|
} };
|
|
706
337
|
}
|
|
707
|
-
infoLog("web:adapter", "creating browser adapter", {
|
|
708
|
-
hookInstalled: Boolean(window.__XSTATE_DEVTOOLS__)
|
|
709
|
-
});
|
|
710
|
-
let warnedMissingHook = false;
|
|
711
338
|
const transport = {
|
|
712
339
|
send(message) {
|
|
713
|
-
|
|
714
|
-
debugLog("web:adapter", "sending message via page hook", {
|
|
715
|
-
type: message.type,
|
|
716
|
-
sessionId: "sessionId" in message ? message.sessionId : void 0
|
|
717
|
-
});
|
|
718
|
-
if (window.__XSTATE_DEVTOOLS__) {
|
|
719
|
-
window.__XSTATE_DEVTOOLS__.send(payload);
|
|
720
|
-
return;
|
|
721
|
-
}
|
|
722
|
-
if (!warnedMissingHook) {
|
|
723
|
-
warnedMissingHook = true;
|
|
724
|
-
warnLog("web:adapter", "page hook missing; using direct window.postMessage fallback");
|
|
725
|
-
}
|
|
726
|
-
window.postMessage(payload, "*");
|
|
340
|
+
window.__XSTATE_DEVTOOLS__?.send({ ...message, __xstateDevtools: true });
|
|
727
341
|
},
|
|
728
342
|
subscribe(handler) {
|
|
729
|
-
infoLog("web:adapter", "subscribing to window messages");
|
|
730
343
|
const onMessage = (evt) => {
|
|
731
344
|
if (evt.source !== window) return;
|
|
732
345
|
const data = evt.data;
|
|
733
346
|
if (!data?.__xstateDevtools) return;
|
|
734
|
-
debugLog("web:adapter", "received message from window bridge", {
|
|
735
|
-
type: data.type,
|
|
736
|
-
sessionId: "sessionId" in data ? data.sessionId : void 0
|
|
737
|
-
});
|
|
738
347
|
handler(data);
|
|
739
348
|
};
|
|
740
349
|
window.addEventListener("message", onMessage);
|
|
741
|
-
return () =>
|
|
742
|
-
infoLog("web:adapter", "unsubscribing from window messages");
|
|
743
|
-
window.removeEventListener("message", onMessage);
|
|
744
|
-
};
|
|
350
|
+
return () => window.removeEventListener("message", onMessage);
|
|
745
351
|
}
|
|
746
352
|
};
|
|
747
|
-
return createInspector(transport, "web"
|
|
353
|
+
return createInspector(transport, "web");
|
|
748
354
|
}
|
|
749
355
|
// Annotate the CommonJS export names for ESM import in node:
|
|
750
356
|
0 && (module.exports = {
|