@agent-scope/playwright 1.0.1
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/browser-bundle.iife.js +994 -0
- package/dist/index.cjs +194 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +122 -0
- package/dist/index.d.ts +122 -0
- package/dist/index.js +185 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,994 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
(() => {
|
|
3
|
+
// ../core/src/serialization.ts
|
|
4
|
+
var DEFAULTS = {
|
|
5
|
+
maxDepth: 5,
|
|
6
|
+
maxStringLength: 200,
|
|
7
|
+
maxArrayLength: 100,
|
|
8
|
+
maxProperties: 50
|
|
9
|
+
};
|
|
10
|
+
function serialize(value, options) {
|
|
11
|
+
const opts = { ...DEFAULTS, ...options };
|
|
12
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
13
|
+
return serializeInner(value, 0, seen, opts);
|
|
14
|
+
}
|
|
15
|
+
function serializeInner(value, depth, seen, opts) {
|
|
16
|
+
if (value === null) {
|
|
17
|
+
return { type: "null", value: null, preview: "null" };
|
|
18
|
+
}
|
|
19
|
+
if (value === void 0) {
|
|
20
|
+
return { type: "undefined", preview: "undefined" };
|
|
21
|
+
}
|
|
22
|
+
if (typeof value === "boolean") {
|
|
23
|
+
return { type: "boolean", value, preview: String(value) };
|
|
24
|
+
}
|
|
25
|
+
if (typeof value === "number") {
|
|
26
|
+
return { type: "number", value, preview: String(value) };
|
|
27
|
+
}
|
|
28
|
+
if (typeof value === "string") {
|
|
29
|
+
if (value.length > opts.maxStringLength) {
|
|
30
|
+
const truncated = value.slice(0, opts.maxStringLength) + "...";
|
|
31
|
+
return { type: "string", value: truncated, preview: `"${truncated}"` };
|
|
32
|
+
}
|
|
33
|
+
return { type: "string", value, preview: `"${value}"` };
|
|
34
|
+
}
|
|
35
|
+
if (typeof value === "bigint") {
|
|
36
|
+
return { type: "bigint", value: `${value.toString()}n`, preview: `${value.toString()}n` };
|
|
37
|
+
}
|
|
38
|
+
if (typeof value === "symbol") {
|
|
39
|
+
const preview = value.toString();
|
|
40
|
+
return { type: "symbol", preview };
|
|
41
|
+
}
|
|
42
|
+
if (typeof value === "function") {
|
|
43
|
+
const raw = Function.prototype.toString.call(value);
|
|
44
|
+
const preview = raw.length > 50 ? raw.slice(0, 50) + " ..." : raw;
|
|
45
|
+
return { type: "function", preview };
|
|
46
|
+
}
|
|
47
|
+
if (typeof value !== "object") {
|
|
48
|
+
return { type: "string", value: String(value), preview: String(value) };
|
|
49
|
+
}
|
|
50
|
+
if (seen.has(value)) {
|
|
51
|
+
return { type: "circular" };
|
|
52
|
+
}
|
|
53
|
+
if (depth >= opts.maxDepth) {
|
|
54
|
+
return { type: "truncated", preview: truncationPreview(value) };
|
|
55
|
+
}
|
|
56
|
+
seen.add(value);
|
|
57
|
+
try {
|
|
58
|
+
if (value instanceof Date) {
|
|
59
|
+
return { type: "date", value: value.toISOString(), preview: value.toISOString() };
|
|
60
|
+
}
|
|
61
|
+
if (value instanceof Map) {
|
|
62
|
+
const entries = [];
|
|
63
|
+
let count = 0;
|
|
64
|
+
for (const [k, v] of value) {
|
|
65
|
+
if (count >= opts.maxProperties) break;
|
|
66
|
+
const serializedKey = serializeInner(k, depth + 1, seen, opts);
|
|
67
|
+
const serializedVal = serializeInner(v, depth + 1, seen, opts);
|
|
68
|
+
entries.push({
|
|
69
|
+
type: "object",
|
|
70
|
+
value: { key: serializedKey, value: serializedVal },
|
|
71
|
+
preview: `[${serializedKey.preview ?? "?"} => ${serializedVal.preview ?? "?"}]`
|
|
72
|
+
});
|
|
73
|
+
count++;
|
|
74
|
+
}
|
|
75
|
+
const truncated = value.size > opts.maxProperties;
|
|
76
|
+
return {
|
|
77
|
+
type: "map",
|
|
78
|
+
value: entries,
|
|
79
|
+
preview: `Map(${value.size})${truncated ? " [truncated]" : ""}`
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (value instanceof Set) {
|
|
83
|
+
const items = [];
|
|
84
|
+
let count = 0;
|
|
85
|
+
for (const v of value) {
|
|
86
|
+
if (count >= opts.maxArrayLength) break;
|
|
87
|
+
items.push(serializeInner(v, depth + 1, seen, opts));
|
|
88
|
+
count++;
|
|
89
|
+
}
|
|
90
|
+
const truncated = value.size > opts.maxArrayLength;
|
|
91
|
+
return {
|
|
92
|
+
type: "set",
|
|
93
|
+
value: items,
|
|
94
|
+
preview: `Set(${value.size})${truncated ? " [truncated]" : ""}`
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
if (Array.isArray(value)) {
|
|
98
|
+
const items = [];
|
|
99
|
+
const limit = Math.min(value.length, opts.maxArrayLength);
|
|
100
|
+
for (let i = 0; i < limit; i++) {
|
|
101
|
+
items.push(serializeInner(value[i], depth + 1, seen, opts));
|
|
102
|
+
}
|
|
103
|
+
const truncated = value.length > opts.maxArrayLength;
|
|
104
|
+
return {
|
|
105
|
+
type: "array",
|
|
106
|
+
value: items,
|
|
107
|
+
preview: `Array(${value.length})${truncated ? " [truncated]" : ""}`
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
return serializeObject(value, depth, seen, opts);
|
|
111
|
+
} finally {
|
|
112
|
+
seen.delete(value);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function serializeObject(value, depth, seen, opts) {
|
|
116
|
+
const ctor = getConstructorName(value);
|
|
117
|
+
if (value instanceof WeakMap || value instanceof WeakSet || typeof WeakRef !== "undefined" && value instanceof WeakRef) {
|
|
118
|
+
return { type: "object", preview: ctor };
|
|
119
|
+
}
|
|
120
|
+
if (value instanceof Error) {
|
|
121
|
+
const props2 = {
|
|
122
|
+
name: serializeInner(value.name, depth + 1, seen, opts),
|
|
123
|
+
message: serializeInner(value.message, depth + 1, seen, opts)
|
|
124
|
+
};
|
|
125
|
+
if (value.stack !== void 0) {
|
|
126
|
+
props2.stack = serializeInner(value.stack, depth + 1, seen, opts);
|
|
127
|
+
}
|
|
128
|
+
return { type: "object", value: props2, preview: `${value.name}: ${value.message}` };
|
|
129
|
+
}
|
|
130
|
+
let keys;
|
|
131
|
+
try {
|
|
132
|
+
keys = Object.keys(value);
|
|
133
|
+
} catch {
|
|
134
|
+
return { type: "object", preview: ctor ?? "Object" };
|
|
135
|
+
}
|
|
136
|
+
const props = {};
|
|
137
|
+
const limit = Math.min(keys.length, opts.maxProperties);
|
|
138
|
+
for (let i = 0; i < limit; i++) {
|
|
139
|
+
const key = keys[i];
|
|
140
|
+
let propValue;
|
|
141
|
+
try {
|
|
142
|
+
propValue = value[key];
|
|
143
|
+
} catch {
|
|
144
|
+
propValue = "[Getter threw]";
|
|
145
|
+
}
|
|
146
|
+
props[key] = serializeInner(propValue, depth + 1, seen, opts);
|
|
147
|
+
}
|
|
148
|
+
const truncated = keys.length > opts.maxProperties;
|
|
149
|
+
const ctorPart = ctor && ctor !== "Object" ? `${ctor} ` : "";
|
|
150
|
+
const preview = `${ctorPart}{${keys.slice(0, 3).join(", ")}${keys.length > 3 ? ", \u2026" : ""}}${truncated ? " [truncated]" : ""}`;
|
|
151
|
+
return { type: "object", value: props, preview };
|
|
152
|
+
}
|
|
153
|
+
function getConstructorName(value) {
|
|
154
|
+
try {
|
|
155
|
+
const ctor = Object.getPrototypeOf(value)?.constructor;
|
|
156
|
+
return ctor?.name ?? "Object";
|
|
157
|
+
} catch {
|
|
158
|
+
return "Object";
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function truncationPreview(value) {
|
|
162
|
+
if (Array.isArray(value)) return `Array(${value.length})`;
|
|
163
|
+
if (value instanceof Map) return `Map(${value.size})`;
|
|
164
|
+
if (value instanceof Set) return `Set(${value.size})`;
|
|
165
|
+
const ctor = typeof value === "object" && value !== null ? getConstructorName(value) : "";
|
|
166
|
+
return ctor || "Object";
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// ../runtime/src/console-interceptor.ts
|
|
170
|
+
var INTERCEPTED_LEVELS = [
|
|
171
|
+
"log",
|
|
172
|
+
"warn",
|
|
173
|
+
"error",
|
|
174
|
+
"info",
|
|
175
|
+
"debug",
|
|
176
|
+
"group",
|
|
177
|
+
"groupCollapsed",
|
|
178
|
+
"table",
|
|
179
|
+
"trace"
|
|
180
|
+
];
|
|
181
|
+
var _entries = [];
|
|
182
|
+
var _originals = {};
|
|
183
|
+
var _installed = false;
|
|
184
|
+
function getCurrentComponentName() {
|
|
185
|
+
try {
|
|
186
|
+
const win = typeof window !== "undefined" ? window : typeof globalThis !== "undefined" ? globalThis : null;
|
|
187
|
+
if (!win) return null;
|
|
188
|
+
const hook = win.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
189
|
+
if (!hook || typeof hook !== "object") return null;
|
|
190
|
+
const fiber = hook._currentFiber ?? hook.currentFiber ?? null;
|
|
191
|
+
if (!fiber) return null;
|
|
192
|
+
return extractFiberName(fiber);
|
|
193
|
+
} catch {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function extractFiberName(fiber) {
|
|
198
|
+
if (!fiber) return null;
|
|
199
|
+
const { type } = fiber;
|
|
200
|
+
if (!type) return null;
|
|
201
|
+
if (typeof type === "function") {
|
|
202
|
+
return type.displayName || type.name || null;
|
|
203
|
+
}
|
|
204
|
+
if (typeof type === "object" && type !== null) {
|
|
205
|
+
if (typeof type.displayName === "string" && type.displayName) {
|
|
206
|
+
return type.displayName;
|
|
207
|
+
}
|
|
208
|
+
if (typeof type.render === "function") {
|
|
209
|
+
return type.render.displayName || type.render.name || null;
|
|
210
|
+
}
|
|
211
|
+
if (type.type) {
|
|
212
|
+
return extractFiberName({ type: type.type });
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
function buildPreview(args) {
|
|
218
|
+
const MAX = 200;
|
|
219
|
+
const parts = args.map((arg) => {
|
|
220
|
+
if (arg === null) return "null";
|
|
221
|
+
if (arg === void 0) return "undefined";
|
|
222
|
+
if (typeof arg === "string") return arg;
|
|
223
|
+
if (typeof arg === "number" || typeof arg === "boolean" || typeof arg === "bigint") {
|
|
224
|
+
return String(arg);
|
|
225
|
+
}
|
|
226
|
+
try {
|
|
227
|
+
return JSON.stringify(arg);
|
|
228
|
+
} catch {
|
|
229
|
+
return String(arg);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
const joined = parts.join(" ");
|
|
233
|
+
return joined.length > MAX ? `${joined.slice(0, MAX - 1)}\u2026` : joined;
|
|
234
|
+
}
|
|
235
|
+
function makeWrapper(level, original) {
|
|
236
|
+
return function scopeConsoleWrapper(...args) {
|
|
237
|
+
original.apply(console, args);
|
|
238
|
+
try {
|
|
239
|
+
const componentName = getCurrentComponentName();
|
|
240
|
+
const timestamp = Date.now();
|
|
241
|
+
const serializedArgs = args.map((a) => serialize(a));
|
|
242
|
+
const preview = buildPreview(args);
|
|
243
|
+
const entry = {
|
|
244
|
+
level,
|
|
245
|
+
args: serializedArgs,
|
|
246
|
+
componentName,
|
|
247
|
+
timestamp,
|
|
248
|
+
preview
|
|
249
|
+
};
|
|
250
|
+
_entries.push(entry);
|
|
251
|
+
} catch {
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function installConsoleInterceptor() {
|
|
256
|
+
if (_installed) return;
|
|
257
|
+
_installed = true;
|
|
258
|
+
for (const level of INTERCEPTED_LEVELS) {
|
|
259
|
+
const original = console[level];
|
|
260
|
+
_originals[level] = original;
|
|
261
|
+
console[level] = makeWrapper(level, original);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function uninstallConsoleInterceptor() {
|
|
265
|
+
if (!_installed) return;
|
|
266
|
+
_installed = false;
|
|
267
|
+
for (const level of INTERCEPTED_LEVELS) {
|
|
268
|
+
const original = _originals[level];
|
|
269
|
+
if (original !== void 0) {
|
|
270
|
+
console[level] = original;
|
|
271
|
+
}
|
|
272
|
+
delete _originals[level];
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
function getConsoleEntries() {
|
|
276
|
+
return _entries.slice();
|
|
277
|
+
}
|
|
278
|
+
function clearConsoleEntries() {
|
|
279
|
+
_entries.splice(0);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// ../runtime/src/devtools-hook.ts
|
|
283
|
+
var _hook = null;
|
|
284
|
+
var _nextRendererID = 1;
|
|
285
|
+
var _rendererListeners = [];
|
|
286
|
+
function createScopeHook() {
|
|
287
|
+
const renderers = /* @__PURE__ */ new Map();
|
|
288
|
+
const hook = {
|
|
289
|
+
isDisabled: false,
|
|
290
|
+
supportsFiber: true,
|
|
291
|
+
_renderers: renderers,
|
|
292
|
+
_isScopeHook: true,
|
|
293
|
+
inject(renderer) {
|
|
294
|
+
const id = _nextRendererID++;
|
|
295
|
+
const entry = {
|
|
296
|
+
id,
|
|
297
|
+
renderer,
|
|
298
|
+
// biome-ignore lint/suspicious/noExplicitAny: React renderer internals
|
|
299
|
+
fiberRoots: /* @__PURE__ */ new Set()
|
|
300
|
+
};
|
|
301
|
+
renderers.set(id, entry);
|
|
302
|
+
for (const listener of _rendererListeners.splice(0)) {
|
|
303
|
+
listener(entry);
|
|
304
|
+
}
|
|
305
|
+
return id;
|
|
306
|
+
},
|
|
307
|
+
onCommitFiberRoot(rendererID, root, _priorityLevel) {
|
|
308
|
+
const entry = renderers.get(rendererID);
|
|
309
|
+
if (entry) {
|
|
310
|
+
entry.fiberRoots.add(root);
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
onCommitFiberUnmount(_rendererID, _fiber) {
|
|
314
|
+
},
|
|
315
|
+
onPostCommitFiberRoot(_rendererID, _root) {
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
return hook;
|
|
319
|
+
}
|
|
320
|
+
function installHook() {
|
|
321
|
+
if (_hook !== null) {
|
|
322
|
+
return _hook;
|
|
323
|
+
}
|
|
324
|
+
const win = typeof window !== "undefined" ? window : null;
|
|
325
|
+
if (win === null) {
|
|
326
|
+
_hook = createScopeHook();
|
|
327
|
+
return _hook;
|
|
328
|
+
}
|
|
329
|
+
const existing = win.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
330
|
+
if (existing && typeof existing === "object") {
|
|
331
|
+
const existingHook = existing;
|
|
332
|
+
if (existingHook._isScopeHook === true) {
|
|
333
|
+
_hook = existing;
|
|
334
|
+
return _hook;
|
|
335
|
+
}
|
|
336
|
+
const scopeHook2 = createScopeHook();
|
|
337
|
+
const originalInject = existingHook.inject;
|
|
338
|
+
existingHook.inject = (renderer) => {
|
|
339
|
+
const originalId = typeof originalInject === "function" ? originalInject.call(existing, renderer) : -1;
|
|
340
|
+
scopeHook2.inject(renderer);
|
|
341
|
+
return originalId;
|
|
342
|
+
};
|
|
343
|
+
existingHook._renderers = scopeHook2._renderers;
|
|
344
|
+
existingHook._isScopeHook = true;
|
|
345
|
+
_hook = scopeHook2;
|
|
346
|
+
return _hook;
|
|
347
|
+
}
|
|
348
|
+
_hook = createScopeHook();
|
|
349
|
+
win.__REACT_DEVTOOLS_GLOBAL_HOOK__ = _hook;
|
|
350
|
+
return _hook;
|
|
351
|
+
}
|
|
352
|
+
function waitForReact(timeout = 1e4) {
|
|
353
|
+
const hook = _hook ?? installHook();
|
|
354
|
+
const existing = Array.from(hook._renderers.values());
|
|
355
|
+
if (existing.length > 0) {
|
|
356
|
+
return Promise.resolve(existing[0]);
|
|
357
|
+
}
|
|
358
|
+
return new Promise((resolve, reject) => {
|
|
359
|
+
const timer = setTimeout(() => {
|
|
360
|
+
const idx = _rendererListeners.indexOf(listener);
|
|
361
|
+
if (idx !== -1) _rendererListeners.splice(idx, 1);
|
|
362
|
+
reject(new Error(`waitForReact: timed out after ${timeout}ms`));
|
|
363
|
+
}, timeout);
|
|
364
|
+
const listener = (renderer) => {
|
|
365
|
+
clearTimeout(timer);
|
|
366
|
+
resolve(renderer);
|
|
367
|
+
};
|
|
368
|
+
_rendererListeners.push(listener);
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// ../runtime/src/error-detector.ts
|
|
373
|
+
var ClassComponent = 1;
|
|
374
|
+
function fiberName(fiber) {
|
|
375
|
+
const { type } = fiber;
|
|
376
|
+
if (!type) return "Anonymous";
|
|
377
|
+
if (typeof type === "string") return type;
|
|
378
|
+
if (typeof type.displayName === "string" && type.displayName) return type.displayName;
|
|
379
|
+
if (typeof type.name === "string" && type.name) return type.name;
|
|
380
|
+
return "Anonymous";
|
|
381
|
+
}
|
|
382
|
+
function isErrorBoundary(fiber) {
|
|
383
|
+
if (fiber.tag !== ClassComponent) return false;
|
|
384
|
+
const type = fiber.type;
|
|
385
|
+
if (!type || typeof type !== "function") return false;
|
|
386
|
+
if (typeof type.getDerivedStateFromError === "function") return true;
|
|
387
|
+
if (type.prototype && typeof type.prototype.componentDidCatch === "function") return true;
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
function extractErrorFromState(memoizedState) {
|
|
391
|
+
if (memoizedState === null || memoizedState === void 0) return null;
|
|
392
|
+
if (memoizedState instanceof Error) return memoizedState;
|
|
393
|
+
if (typeof memoizedState !== "object") return null;
|
|
394
|
+
if (memoizedState.hasError === true && memoizedState.error instanceof Error) {
|
|
395
|
+
return memoizedState.error;
|
|
396
|
+
}
|
|
397
|
+
if (memoizedState.error instanceof Error) return memoizedState.error;
|
|
398
|
+
for (const key of Object.keys(memoizedState)) {
|
|
399
|
+
if (memoizedState[key] instanceof Error) return memoizedState[key];
|
|
400
|
+
}
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
function findNearestBoundaryName(fiber) {
|
|
404
|
+
let current = fiber.return ?? null;
|
|
405
|
+
while (current !== null) {
|
|
406
|
+
if (isErrorBoundary(current)) {
|
|
407
|
+
return fiberName(current);
|
|
408
|
+
}
|
|
409
|
+
current = current.return ?? null;
|
|
410
|
+
}
|
|
411
|
+
return null;
|
|
412
|
+
}
|
|
413
|
+
function detectErrors(rootFiber) {
|
|
414
|
+
const results = [];
|
|
415
|
+
const visited = /* @__PURE__ */ new Set();
|
|
416
|
+
function walk(fiber) {
|
|
417
|
+
if (fiber === null || fiber === void 0) return;
|
|
418
|
+
if (visited.has(fiber)) return;
|
|
419
|
+
visited.add(fiber);
|
|
420
|
+
if (isErrorBoundary(fiber)) {
|
|
421
|
+
const error = extractErrorFromState(fiber.memoizedState);
|
|
422
|
+
if (error !== null) {
|
|
423
|
+
const throwingChild = fiber.child;
|
|
424
|
+
const componentName = throwingChild ? fiberName(throwingChild) : fiberName(fiber);
|
|
425
|
+
const boundaryName = fiberName(fiber);
|
|
426
|
+
const enclosingBoundary = findNearestBoundaryName(fiber);
|
|
427
|
+
results.push({
|
|
428
|
+
message: error.message ?? String(error),
|
|
429
|
+
name: error.name ?? "Error",
|
|
430
|
+
stack: error.stack ?? null,
|
|
431
|
+
source: null,
|
|
432
|
+
// Stack parsing is left to consumers
|
|
433
|
+
componentName,
|
|
434
|
+
timestamp: Date.now(),
|
|
435
|
+
capturedBy: "boundary",
|
|
436
|
+
// Store boundary name as a non-standard extension that typed consumers
|
|
437
|
+
// can access. The interface only requires the defined fields.
|
|
438
|
+
...{ boundaryName: enclosingBoundary ?? boundaryName }
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
walk(fiber.child ?? null);
|
|
443
|
+
walk(fiber.sibling ?? null);
|
|
444
|
+
}
|
|
445
|
+
walk(rootFiber);
|
|
446
|
+
return results;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// ../runtime/src/context-extractor.ts
|
|
450
|
+
var CONTEXT_CONSUMER_TAG = 9;
|
|
451
|
+
function resolveContextName(context) {
|
|
452
|
+
if (!context || typeof context !== "object") return null;
|
|
453
|
+
if (typeof context.displayName === "string" && context.displayName) {
|
|
454
|
+
return context.displayName;
|
|
455
|
+
}
|
|
456
|
+
const currentValue = context._currentValue;
|
|
457
|
+
if (currentValue !== null && currentValue !== void 0 && typeof currentValue === "object") {
|
|
458
|
+
const ctorName = currentValue.constructor?.name;
|
|
459
|
+
if (typeof ctorName === "string" && ctorName && ctorName !== "Object" && ctorName !== "Array") {
|
|
460
|
+
return ctorName;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
return null;
|
|
464
|
+
}
|
|
465
|
+
function readContextDependencies(fiber) {
|
|
466
|
+
const first = (
|
|
467
|
+
// biome-ignore lint/suspicious/noExplicitAny: React fiber internals
|
|
468
|
+
fiber.dependencies?.firstContext ?? // React 16 legacy field
|
|
469
|
+
// biome-ignore lint/suspicious/noExplicitAny: React fiber internals
|
|
470
|
+
fiber.contextDependencies?.first ?? null
|
|
471
|
+
);
|
|
472
|
+
if (first === null || first === void 0) return [];
|
|
473
|
+
const deps = [];
|
|
474
|
+
let node = first;
|
|
475
|
+
while (node !== null && node !== void 0) {
|
|
476
|
+
deps.push(node);
|
|
477
|
+
node = node.next ?? null;
|
|
478
|
+
}
|
|
479
|
+
return deps;
|
|
480
|
+
}
|
|
481
|
+
function extractContextConsumptions(fiber) {
|
|
482
|
+
if (fiber.tag === CONTEXT_CONSUMER_TAG) {
|
|
483
|
+
const context = fiber.type;
|
|
484
|
+
if (context && typeof context === "object") {
|
|
485
|
+
const contextName = resolveContextName(context);
|
|
486
|
+
const raw = context._currentValue;
|
|
487
|
+
return [
|
|
488
|
+
{
|
|
489
|
+
contextName,
|
|
490
|
+
value: serialize(raw),
|
|
491
|
+
didTriggerRender: false
|
|
492
|
+
}
|
|
493
|
+
];
|
|
494
|
+
}
|
|
495
|
+
return [];
|
|
496
|
+
}
|
|
497
|
+
const deps = readContextDependencies(fiber);
|
|
498
|
+
if (deps.length === 0) return [];
|
|
499
|
+
const consumptions = [];
|
|
500
|
+
for (const dep of deps) {
|
|
501
|
+
const context = dep.context ?? dep.observedBits ?? null;
|
|
502
|
+
if (!context || typeof context !== "object") continue;
|
|
503
|
+
const raw = context._currentValue;
|
|
504
|
+
const contextName = resolveContextName(context);
|
|
505
|
+
consumptions.push({
|
|
506
|
+
contextName,
|
|
507
|
+
value: serialize(raw),
|
|
508
|
+
didTriggerRender: false
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
return consumptions;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// ../runtime/src/hooks-extractor.ts
|
|
515
|
+
var HookLayout = 4;
|
|
516
|
+
function isEffectNode(node) {
|
|
517
|
+
const ms = node.memoizedState;
|
|
518
|
+
if (ms === null || typeof ms !== "object") return false;
|
|
519
|
+
const obj = ms;
|
|
520
|
+
return typeof obj.create === "function" && "deps" in obj && typeof obj.tag === "number";
|
|
521
|
+
}
|
|
522
|
+
function isRefNode(node) {
|
|
523
|
+
if (node.queue != null) return false;
|
|
524
|
+
const ms = node.memoizedState;
|
|
525
|
+
if (ms === null || typeof ms !== "object" || Array.isArray(ms)) return false;
|
|
526
|
+
const keys = Object.keys(ms);
|
|
527
|
+
return keys.length === 1 && keys[0] === "current";
|
|
528
|
+
}
|
|
529
|
+
function isMemoTuple(node) {
|
|
530
|
+
if (node.queue != null) return false;
|
|
531
|
+
const ms = node.memoizedState;
|
|
532
|
+
if (!Array.isArray(ms) || ms.length !== 2) return false;
|
|
533
|
+
return ms[1] === null || Array.isArray(ms[1]);
|
|
534
|
+
}
|
|
535
|
+
function isStateOrReducerNode(node) {
|
|
536
|
+
return node.queue != null && typeof node.queue === "object" && typeof node.queue.dispatch === "function";
|
|
537
|
+
}
|
|
538
|
+
function isReducerNode(node) {
|
|
539
|
+
if (!isStateOrReducerNode(node)) return false;
|
|
540
|
+
const q = node.queue;
|
|
541
|
+
if (typeof q.reducer === "function") return true;
|
|
542
|
+
const lrr = q.lastRenderedReducer;
|
|
543
|
+
if (typeof lrr !== "function") return false;
|
|
544
|
+
const name = lrr.name ?? "";
|
|
545
|
+
return name !== "basicStateReducer" && name !== "";
|
|
546
|
+
}
|
|
547
|
+
function classifyEffectType(effect) {
|
|
548
|
+
if (effect.tag & HookLayout) return "useLayoutEffect";
|
|
549
|
+
return "useEffect";
|
|
550
|
+
}
|
|
551
|
+
function serializeDeps(deps) {
|
|
552
|
+
if (deps === null || deps === void 0) return null;
|
|
553
|
+
if (!Array.isArray(deps)) return null;
|
|
554
|
+
return deps.map((d) => serialize(d));
|
|
555
|
+
}
|
|
556
|
+
function extractHooks(fiber) {
|
|
557
|
+
if (fiber == null) return [];
|
|
558
|
+
let node = fiber.memoizedState ?? null;
|
|
559
|
+
if (node === null) return [];
|
|
560
|
+
const hooks = [];
|
|
561
|
+
while (node !== null) {
|
|
562
|
+
hooks.push(classifyNode(node));
|
|
563
|
+
node = node.next ?? null;
|
|
564
|
+
}
|
|
565
|
+
return hooks;
|
|
566
|
+
}
|
|
567
|
+
function classifyNode(node) {
|
|
568
|
+
if (isEffectNode(node)) {
|
|
569
|
+
const effect = node.memoizedState;
|
|
570
|
+
const hookType = classifyEffectType(effect);
|
|
571
|
+
return {
|
|
572
|
+
type: hookType,
|
|
573
|
+
name: null,
|
|
574
|
+
value: serialize(void 0),
|
|
575
|
+
deps: serializeDeps(effect.deps),
|
|
576
|
+
hasCleanup: typeof effect.destroy === "function"
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
if (isRefNode(node)) {
|
|
580
|
+
const ref = node.memoizedState;
|
|
581
|
+
return {
|
|
582
|
+
type: "useRef",
|
|
583
|
+
name: null,
|
|
584
|
+
value: serialize(ref.current),
|
|
585
|
+
deps: null,
|
|
586
|
+
hasCleanup: null
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
if (isMemoTuple(node)) {
|
|
590
|
+
const [val, deps] = node.memoizedState;
|
|
591
|
+
const hookType = typeof val === "function" ? "useCallback" : "useMemo";
|
|
592
|
+
return {
|
|
593
|
+
type: hookType,
|
|
594
|
+
name: null,
|
|
595
|
+
value: serialize(val),
|
|
596
|
+
deps: serializeDeps(deps),
|
|
597
|
+
hasCleanup: null
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
if (isStateOrReducerNode(node)) {
|
|
601
|
+
const hookType = isReducerNode(node) ? "useReducer" : "useState";
|
|
602
|
+
return {
|
|
603
|
+
type: hookType,
|
|
604
|
+
name: null,
|
|
605
|
+
value: serialize(node.memoizedState),
|
|
606
|
+
deps: null,
|
|
607
|
+
hasCleanup: null
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
return {
|
|
611
|
+
type: "custom",
|
|
612
|
+
name: null,
|
|
613
|
+
value: serialize(node.memoizedState),
|
|
614
|
+
deps: null,
|
|
615
|
+
hasCleanup: null
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
// ../runtime/src/profiler.ts
|
|
620
|
+
var _profilingData = /* @__PURE__ */ new Map();
|
|
621
|
+
var _fiberRefMap = /* @__PURE__ */ new WeakMap();
|
|
622
|
+
var _syntheticIdCounter = -1;
|
|
623
|
+
var _installed2 = false;
|
|
624
|
+
function fiberId(fiber) {
|
|
625
|
+
if (typeof fiber._debugID === "number") {
|
|
626
|
+
return fiber._debugID;
|
|
627
|
+
}
|
|
628
|
+
const existing = _fiberRefMap.get(fiber);
|
|
629
|
+
if (existing !== void 0) return existing;
|
|
630
|
+
const id = _syntheticIdCounter--;
|
|
631
|
+
_fiberRefMap.set(fiber, id);
|
|
632
|
+
return id;
|
|
633
|
+
}
|
|
634
|
+
function walkCommittedFibers(fiber) {
|
|
635
|
+
if (fiber === null || fiber === void 0) return;
|
|
636
|
+
const actualDuration = typeof fiber.actualDuration === "number" ? fiber.actualDuration : -1;
|
|
637
|
+
const selfBaseDuration = typeof fiber.selfBaseDuration === "number" ? fiber.selfBaseDuration : 0;
|
|
638
|
+
if (actualDuration >= 0) {
|
|
639
|
+
const id = fiberId(fiber);
|
|
640
|
+
const existing = _profilingData.get(id);
|
|
641
|
+
if (existing !== void 0) {
|
|
642
|
+
existing.renderCount += 1;
|
|
643
|
+
existing.renderDuration += selfBaseDuration;
|
|
644
|
+
} else {
|
|
645
|
+
_profilingData.set(id, {
|
|
646
|
+
renderCount: 1,
|
|
647
|
+
renderDuration: selfBaseDuration
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
walkCommittedFibers(fiber.child ?? null);
|
|
652
|
+
walkCommittedFibers(fiber.sibling ?? null);
|
|
653
|
+
}
|
|
654
|
+
function installProfiler(hook) {
|
|
655
|
+
if (_installed2) return;
|
|
656
|
+
_installed2 = true;
|
|
657
|
+
const originalOnCommit2 = hook.onCommitFiberRoot.bind(hook);
|
|
658
|
+
hook.onCommitFiberRoot = (rendererID, root, priorityLevel) => {
|
|
659
|
+
originalOnCommit2(rendererID, root, priorityLevel);
|
|
660
|
+
const wipRoot = root?.current?.alternate ?? root?.current ?? null;
|
|
661
|
+
if (wipRoot !== null) {
|
|
662
|
+
walkCommittedFibers(wipRoot);
|
|
663
|
+
}
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
function getProfilingData(fiberIdParam) {
|
|
667
|
+
const record = _profilingData.get(fiberIdParam);
|
|
668
|
+
if (record === void 0) return null;
|
|
669
|
+
return { renderCount: record.renderCount, renderDuration: record.renderDuration };
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// ../runtime/src/fiber-walker.ts
|
|
673
|
+
var FunctionComponent = 0;
|
|
674
|
+
var ClassComponent2 = 1;
|
|
675
|
+
var IndeterminateComponent = 2;
|
|
676
|
+
var HostRoot = 3;
|
|
677
|
+
var HostComponent = 5;
|
|
678
|
+
var HostText = 6;
|
|
679
|
+
var Fragment = 7;
|
|
680
|
+
var ForwardRef = 11;
|
|
681
|
+
var SuspenseComponent = 13;
|
|
682
|
+
var MemoComponent = 14;
|
|
683
|
+
var SimpleMemoComponent = 15;
|
|
684
|
+
var _idCounter = 1;
|
|
685
|
+
function nextId() {
|
|
686
|
+
return _idCounter++;
|
|
687
|
+
}
|
|
688
|
+
var INFERRED_PROPERTY_NAMES = /* @__PURE__ */ new Set(["render", "type", "forward_ref", "memo"]);
|
|
689
|
+
function isUserSuppliedName(name, tag) {
|
|
690
|
+
if (typeof name !== "string" || !name) return false;
|
|
691
|
+
if ((tag === ForwardRef || tag === MemoComponent || tag === SimpleMemoComponent) && INFERRED_PROPERTY_NAMES.has(name)) {
|
|
692
|
+
return false;
|
|
693
|
+
}
|
|
694
|
+
return true;
|
|
695
|
+
}
|
|
696
|
+
function extractName(fiber) {
|
|
697
|
+
const { type, tag } = fiber;
|
|
698
|
+
if (type === null || type === void 0) {
|
|
699
|
+
if (tag === HostRoot) return "HostRoot";
|
|
700
|
+
if (tag === Fragment) return "Fragment";
|
|
701
|
+
if (tag === HostText) return "#text";
|
|
702
|
+
return "Anonymous";
|
|
703
|
+
}
|
|
704
|
+
if (typeof type === "string") {
|
|
705
|
+
return type;
|
|
706
|
+
}
|
|
707
|
+
if (typeof type.displayName === "string" && type.displayName) {
|
|
708
|
+
return type.displayName;
|
|
709
|
+
}
|
|
710
|
+
if (tag === ForwardRef || type.$$typeof && String(type.$$typeof).includes("forward_ref")) {
|
|
711
|
+
const render = type.render;
|
|
712
|
+
if (render) {
|
|
713
|
+
if (typeof render.displayName === "string" && render.displayName) return render.displayName;
|
|
714
|
+
if (isUserSuppliedName(render.name, tag)) return render.name;
|
|
715
|
+
}
|
|
716
|
+
return "ForwardRef";
|
|
717
|
+
}
|
|
718
|
+
if (tag === MemoComponent || tag === SimpleMemoComponent || type.$$typeof && String(type.$$typeof).includes("memo")) {
|
|
719
|
+
const inner = type.type;
|
|
720
|
+
if (inner) {
|
|
721
|
+
if (typeof inner.displayName === "string" && inner.displayName) return inner.displayName;
|
|
722
|
+
if (isUserSuppliedName(inner.name, tag)) return inner.name;
|
|
723
|
+
}
|
|
724
|
+
return "Memo";
|
|
725
|
+
}
|
|
726
|
+
if (isUserSuppliedName(type.name, tag)) {
|
|
727
|
+
return type.name;
|
|
728
|
+
}
|
|
729
|
+
return "Anonymous";
|
|
730
|
+
}
|
|
731
|
+
function classifyType(fiber) {
|
|
732
|
+
const { tag, type } = fiber;
|
|
733
|
+
switch (tag) {
|
|
734
|
+
case FunctionComponent:
|
|
735
|
+
case IndeterminateComponent:
|
|
736
|
+
return "function";
|
|
737
|
+
case ClassComponent2:
|
|
738
|
+
return "class";
|
|
739
|
+
case ForwardRef:
|
|
740
|
+
return "forward_ref";
|
|
741
|
+
case MemoComponent:
|
|
742
|
+
case SimpleMemoComponent:
|
|
743
|
+
return "memo";
|
|
744
|
+
case HostComponent:
|
|
745
|
+
case HostText:
|
|
746
|
+
return "host";
|
|
747
|
+
default:
|
|
748
|
+
if (type && typeof type === "object") {
|
|
749
|
+
const typeofStr = String(type.$$typeof ?? "");
|
|
750
|
+
if (typeofStr.includes("forward_ref")) return "forward_ref";
|
|
751
|
+
if (typeofStr.includes("memo")) return "memo";
|
|
752
|
+
}
|
|
753
|
+
return "function";
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
function extractSource(fiber) {
|
|
757
|
+
if (fiber._debugSource) {
|
|
758
|
+
const { fileName, lineNumber, columnNumber } = fiber._debugSource;
|
|
759
|
+
return {
|
|
760
|
+
fileName: String(fileName),
|
|
761
|
+
lineNumber: Number(lineNumber),
|
|
762
|
+
columnNumber: Number(columnNumber)
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
const scopeSource = fiber.memoizedProps?.__scopeSource;
|
|
766
|
+
if (scopeSource && typeof scopeSource === "object") {
|
|
767
|
+
const { fileName, lineNumber, columnNumber } = scopeSource;
|
|
768
|
+
if (typeof fileName === "string" && typeof lineNumber === "number" && typeof columnNumber === "number") {
|
|
769
|
+
return { fileName, lineNumber, columnNumber };
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
return null;
|
|
773
|
+
}
|
|
774
|
+
function shouldSkip(fiber, includeHost) {
|
|
775
|
+
const { tag } = fiber;
|
|
776
|
+
if (tag === HostRoot || tag === HostText || tag === Fragment || tag === SuspenseComponent) {
|
|
777
|
+
return true;
|
|
778
|
+
}
|
|
779
|
+
if (tag === HostComponent && !includeHost) {
|
|
780
|
+
return true;
|
|
781
|
+
}
|
|
782
|
+
return false;
|
|
783
|
+
}
|
|
784
|
+
function walkFiberInner(fiber, includeHost, visited) {
|
|
785
|
+
if (fiber === null || fiber === void 0) return null;
|
|
786
|
+
if (visited.has(fiber)) return null;
|
|
787
|
+
if (shouldSkip(fiber, includeHost)) {
|
|
788
|
+
return null;
|
|
789
|
+
}
|
|
790
|
+
visited.add(fiber);
|
|
791
|
+
const id = typeof fiber._debugID === "number" ? fiber._debugID : nextId();
|
|
792
|
+
const profilingData = getProfilingData(id);
|
|
793
|
+
const children = collectChildren(fiber, includeHost, visited);
|
|
794
|
+
const node = {
|
|
795
|
+
id,
|
|
796
|
+
name: extractName(fiber),
|
|
797
|
+
type: classifyType(fiber),
|
|
798
|
+
source: extractSource(fiber),
|
|
799
|
+
props: serialize(fiber.memoizedProps ?? {}),
|
|
800
|
+
state: extractHooks(fiber),
|
|
801
|
+
context: extractContextConsumptions(fiber),
|
|
802
|
+
renderCount: profilingData?.renderCount ?? 1,
|
|
803
|
+
renderDuration: profilingData?.renderDuration ?? 0,
|
|
804
|
+
children
|
|
805
|
+
};
|
|
806
|
+
return node;
|
|
807
|
+
}
|
|
808
|
+
function collectChildren(fiber, includeHost, visited) {
|
|
809
|
+
const nodes = [];
|
|
810
|
+
let current = fiber.child ?? null;
|
|
811
|
+
while (current !== null) {
|
|
812
|
+
if (visited.has(current)) {
|
|
813
|
+
current = current.sibling ?? null;
|
|
814
|
+
continue;
|
|
815
|
+
}
|
|
816
|
+
if (shouldSkip(current, includeHost)) {
|
|
817
|
+
const promoted = collectChildren(current, includeHost, visited);
|
|
818
|
+
nodes.push(...promoted);
|
|
819
|
+
} else {
|
|
820
|
+
const node = walkFiberInner(current, includeHost, visited);
|
|
821
|
+
if (node !== null) {
|
|
822
|
+
nodes.push(node);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
current = current.sibling ?? null;
|
|
826
|
+
}
|
|
827
|
+
return nodes;
|
|
828
|
+
}
|
|
829
|
+
function walkFiberRoot(fiberRoot, options = {}) {
|
|
830
|
+
if (!fiberRoot) return null;
|
|
831
|
+
const hostRootFiber = fiberRoot.current ?? null;
|
|
832
|
+
if (!hostRootFiber) return null;
|
|
833
|
+
const includeHost = options.includeHostElements ?? false;
|
|
834
|
+
const visited = /* @__PURE__ */ new Set();
|
|
835
|
+
const children = collectChildren(hostRootFiber, includeHost, visited);
|
|
836
|
+
if (children.length === 0) return null;
|
|
837
|
+
if (children.length === 1) return children[0] ?? null;
|
|
838
|
+
return {
|
|
839
|
+
id: nextId(),
|
|
840
|
+
name: "Root",
|
|
841
|
+
type: "function",
|
|
842
|
+
source: null,
|
|
843
|
+
props: serialize({}),
|
|
844
|
+
state: [],
|
|
845
|
+
context: [],
|
|
846
|
+
renderCount: 1,
|
|
847
|
+
renderDuration: 0,
|
|
848
|
+
children
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
// ../runtime/src/suspense-detector.ts
|
|
853
|
+
var SuspenseComponent2 = 13;
|
|
854
|
+
var HostText2 = 6;
|
|
855
|
+
function nearestAncestorName(fiber) {
|
|
856
|
+
let current = fiber.return ?? null;
|
|
857
|
+
while (current !== null) {
|
|
858
|
+
const { type } = current;
|
|
859
|
+
if (type && typeof type !== "string") {
|
|
860
|
+
const name = type.displayName ?? type.name;
|
|
861
|
+
if (typeof name === "string" && name) return name;
|
|
862
|
+
}
|
|
863
|
+
current = current.return ?? null;
|
|
864
|
+
}
|
|
865
|
+
return "Unknown";
|
|
866
|
+
}
|
|
867
|
+
function extractFallbackName(fiber) {
|
|
868
|
+
const primary = fiber.child ?? null;
|
|
869
|
+
const fallback = primary?.sibling ?? null;
|
|
870
|
+
if (!fallback) return null;
|
|
871
|
+
const { type, tag } = fallback;
|
|
872
|
+
if (tag === HostText2) return null;
|
|
873
|
+
if (typeof type === "string") return type;
|
|
874
|
+
if (type && typeof type.displayName === "string" && type.displayName) return type.displayName;
|
|
875
|
+
if (type && typeof type.name === "string" && type.name) return type.name;
|
|
876
|
+
return null;
|
|
877
|
+
}
|
|
878
|
+
function classifyStatus(memoizedState) {
|
|
879
|
+
if (memoizedState === null || memoizedState === void 0) {
|
|
880
|
+
return false;
|
|
881
|
+
}
|
|
882
|
+
if (typeof memoizedState === "object" && memoizedState.dehydrated !== void 0 && memoizedState.dehydrated !== null) {
|
|
883
|
+
return true;
|
|
884
|
+
}
|
|
885
|
+
if (typeof memoizedState === "object" && typeof memoizedState.then === "function") {
|
|
886
|
+
return true;
|
|
887
|
+
}
|
|
888
|
+
return true;
|
|
889
|
+
}
|
|
890
|
+
function detectSuspenseBoundaries(rootFiber) {
|
|
891
|
+
const results = [];
|
|
892
|
+
const visited = /* @__PURE__ */ new Set();
|
|
893
|
+
function walk(fiber) {
|
|
894
|
+
if (fiber === null || fiber === void 0) return;
|
|
895
|
+
if (visited.has(fiber)) return;
|
|
896
|
+
visited.add(fiber);
|
|
897
|
+
if (fiber.tag === SuspenseComponent2) {
|
|
898
|
+
const isSuspended = classifyStatus(fiber.memoizedState);
|
|
899
|
+
const componentName = nearestAncestorName(fiber);
|
|
900
|
+
const fallbackName = extractFallbackName(fiber);
|
|
901
|
+
const id = typeof fiber._debugID === "number" ? fiber._debugID : fiber.index;
|
|
902
|
+
results.push({
|
|
903
|
+
id,
|
|
904
|
+
componentName,
|
|
905
|
+
isSuspended,
|
|
906
|
+
suspendedDuration: null,
|
|
907
|
+
// timing not available at capture time
|
|
908
|
+
fallbackName,
|
|
909
|
+
source: fiber._debugSource ? {
|
|
910
|
+
fileName: String(fiber._debugSource.fileName),
|
|
911
|
+
lineNumber: Number(fiber._debugSource.lineNumber),
|
|
912
|
+
columnNumber: Number(fiber._debugSource.columnNumber)
|
|
913
|
+
} : null
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
walk(fiber.child ?? null);
|
|
917
|
+
walk(fiber.sibling ?? null);
|
|
918
|
+
}
|
|
919
|
+
walk(rootFiber);
|
|
920
|
+
return results;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
// ../runtime/src/capture.ts
|
|
924
|
+
async function capture(options = {}) {
|
|
925
|
+
const startTime = Date.now();
|
|
926
|
+
const hook = installHook();
|
|
927
|
+
installProfiler(hook);
|
|
928
|
+
installConsoleInterceptor();
|
|
929
|
+
clearConsoleEntries();
|
|
930
|
+
const url = options.url ?? (typeof window !== "undefined" ? window.location.href : "unknown");
|
|
931
|
+
try {
|
|
932
|
+
const renderer = await waitForReact(options.reactTimeout ?? 1e4);
|
|
933
|
+
const fiberRoot = Array.from(renderer.fiberRoots)[0] ?? null;
|
|
934
|
+
if (!fiberRoot) {
|
|
935
|
+
throw new Error(
|
|
936
|
+
"capture(): React renderer registered but no fiber roots found. Make sure React has rendered at least one component."
|
|
937
|
+
);
|
|
938
|
+
}
|
|
939
|
+
const walkOptions = {
|
|
940
|
+
includeHostElements: options.includeHostElements ?? false
|
|
941
|
+
};
|
|
942
|
+
const tree = walkFiberRoot(fiberRoot, walkOptions);
|
|
943
|
+
if (!tree) {
|
|
944
|
+
throw new Error(
|
|
945
|
+
"capture(): Fiber tree is empty. Make sure React has rendered at least one component."
|
|
946
|
+
);
|
|
947
|
+
}
|
|
948
|
+
const hostRootFiber = fiberRoot.current ?? null;
|
|
949
|
+
const rootChild = hostRootFiber?.child ?? null;
|
|
950
|
+
const errors = detectErrors(rootChild);
|
|
951
|
+
const suspenseBoundaries = detectSuspenseBoundaries(rootChild);
|
|
952
|
+
const capturedIn = Date.now() - startTime;
|
|
953
|
+
const consoleEntries = getConsoleEntries();
|
|
954
|
+
return {
|
|
955
|
+
url,
|
|
956
|
+
timestamp: startTime,
|
|
957
|
+
capturedIn,
|
|
958
|
+
tree,
|
|
959
|
+
consoleEntries,
|
|
960
|
+
errors,
|
|
961
|
+
suspenseBoundaries
|
|
962
|
+
};
|
|
963
|
+
} finally {
|
|
964
|
+
uninstallConsoleInterceptor();
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
// src/browser-entry.ts
|
|
969
|
+
var scopeHook = installHook();
|
|
970
|
+
var hookObj = scopeHook;
|
|
971
|
+
if (!hookObj.renderers) {
|
|
972
|
+
const renderersProxy = /* @__PURE__ */ new Map();
|
|
973
|
+
const origInject = scopeHook.inject.bind(scopeHook);
|
|
974
|
+
scopeHook.inject = (renderer) => {
|
|
975
|
+
const id = origInject(renderer);
|
|
976
|
+
renderersProxy.set(id, renderer);
|
|
977
|
+
return id;
|
|
978
|
+
};
|
|
979
|
+
hookObj.renderers = renderersProxy;
|
|
980
|
+
}
|
|
981
|
+
var resolveFirstCommit;
|
|
982
|
+
var firstCommit = new Promise((res) => {
|
|
983
|
+
resolveFirstCommit = res;
|
|
984
|
+
});
|
|
985
|
+
var originalOnCommit = scopeHook.onCommitFiberRoot.bind(scopeHook);
|
|
986
|
+
scopeHook.onCommitFiberRoot = (rendererID, root, priorityLevel) => {
|
|
987
|
+
originalOnCommit(rendererID, root, priorityLevel);
|
|
988
|
+
resolveFirstCommit();
|
|
989
|
+
};
|
|
990
|
+
window.__SCOPE_CAPTURE__ = async () => {
|
|
991
|
+
await firstCommit;
|
|
992
|
+
return capture();
|
|
993
|
+
};
|
|
994
|
+
})();
|