@flemo/devtools 0.6.0 → 0.7.0
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/__tests__/swipeProbe.test.d.ts +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.mjs +367 -310
- package/dist/noop.d.ts +4 -0
- package/dist/noop.mjs +2 -2
- package/dist/swipeProbe.d.ts +52 -0
- package/package.json +6 -6
package/dist/index.mjs
CHANGED
|
@@ -201,17 +201,17 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
201
201
|
}
|
|
202
202
|
e.stalledFrames += 1, e.stallRunMs += n, e.stallRunMs > e.longestStallMs && (e.longestStallMs = e.stallRunMs);
|
|
203
203
|
}
|
|
204
|
-
},
|
|
204
|
+
}, R = (e, t) => {
|
|
205
205
|
let n = t.style;
|
|
206
206
|
if (!n || n.animation === "") return;
|
|
207
207
|
e.evidence.inlineSuppression = !0;
|
|
208
208
|
let r = se(n), i = e.lastPose.get(t);
|
|
209
209
|
i !== void 0 && i !== r && (e.evidence.inlineAdvance = !0), e.lastPose.set(t, r);
|
|
210
|
-
},
|
|
210
|
+
}, le = (e, t) => {
|
|
211
211
|
for (let n of t) {
|
|
212
212
|
let t = n.getAnimations, r = e.clocks.get(n);
|
|
213
213
|
if (r !== void 0 && r.playState !== "finished") {
|
|
214
|
-
r.playState === "running" && (e.evidence.compiledAnimation = !0),
|
|
214
|
+
r.playState === "running" && (e.evidence.compiledAnimation = !0), R(e, n);
|
|
215
215
|
continue;
|
|
216
216
|
}
|
|
217
217
|
if (typeof t == "function") try {
|
|
@@ -220,21 +220,21 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
220
220
|
typeof t == "string" && t.startsWith("flemo-") && (e.clocks.set(n, r), r.playState === "running" && (e.evidence.compiledAnimation = !0));
|
|
221
221
|
}
|
|
222
222
|
} catch {}
|
|
223
|
-
|
|
223
|
+
R(e, n);
|
|
224
224
|
}
|
|
225
|
-
},
|
|
225
|
+
}, ue = (e) => ({
|
|
226
226
|
sampledFrames: e.releasedFrames,
|
|
227
227
|
stalledFrames: e.stalledFrames,
|
|
228
228
|
longestStallMs: ie(e.longestStallMs),
|
|
229
229
|
pausedAfterRelease: e.pausedAfterRelease,
|
|
230
230
|
holdReassertedAtMs: e.holdReassertedAtMs,
|
|
231
231
|
tailFrames: e.tailFrames
|
|
232
|
-
}),
|
|
232
|
+
}), z = 200, de = (e) => {
|
|
233
233
|
let t = [];
|
|
234
234
|
for (let n of e) for (let e of Array.from(n.querySelectorAll("img"))) t.push(e);
|
|
235
235
|
return t;
|
|
236
236
|
}, fe = (e) => {
|
|
237
|
-
let t = new Set(
|
|
237
|
+
let t = new Set(de(e).filter((e) => !e.complete));
|
|
238
238
|
return {
|
|
239
239
|
tracked: t,
|
|
240
240
|
loadingAtStart: t.size,
|
|
@@ -242,11 +242,11 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
242
242
|
held: /* @__PURE__ */ new Set()
|
|
243
243
|
};
|
|
244
244
|
}, pe = (e, t, n) => {
|
|
245
|
-
if (!(e.tracked.size >=
|
|
245
|
+
if (!(e.tracked.size >= z)) for (let r of Array.from(n)) {
|
|
246
246
|
if (!(r instanceof Element) || !t.some((e) => e === r || e.contains(r))) continue;
|
|
247
247
|
let n = r instanceof HTMLImageElement ? [r] : Array.from(r.querySelectorAll("img"));
|
|
248
248
|
for (let t of n) if (!(t.complete || e.tracked.has(t))) {
|
|
249
|
-
if (e.tracked.size >=
|
|
249
|
+
if (e.tracked.size >= z) return;
|
|
250
250
|
e.tracked.add(t), e.addedDuringFlight += 1;
|
|
251
251
|
}
|
|
252
252
|
}
|
|
@@ -304,7 +304,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
304
304
|
}, ve = (e) => {
|
|
305
305
|
let t = e.inlineSuppression || e.inlineAdvance;
|
|
306
306
|
return t && e.compiledAnimation ? "mixed" : t ? "inline" : e.compiledAnimation ? "compiled" : "unknown";
|
|
307
|
-
}, ye = (e) => e === "PUSHING" ? "PUSH" : e === "POPPING" ? "POP" : e === "REPLACING" ? "REPLACE" : null,
|
|
307
|
+
}, ye = (e) => e === "PUSHING" ? "PUSH" : e === "POPPING" ? "POP" : e === "REPLACING" ? "REPLACE" : null, H = (e) => {
|
|
308
308
|
let t = /^matrix3d\(([^)]+)\)$/.exec(e.trim());
|
|
309
309
|
if (t) {
|
|
310
310
|
let e = t[1].split(",").map((e) => Number(e.trim()));
|
|
@@ -316,7 +316,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
316
316
|
return e.length === 6 && Number.isFinite(e[4]) ? e[4] : null;
|
|
317
317
|
}
|
|
318
318
|
return null;
|
|
319
|
-
},
|
|
319
|
+
}, U = (e) => {
|
|
320
320
|
if (e) return [];
|
|
321
321
|
let t = [];
|
|
322
322
|
for (let [e, n] of [[h, "image reveal hold"], [g, "arrival hold"]]) {
|
|
@@ -324,7 +324,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
324
324
|
r > 0 && t.push(`${r} × ${n} (${e}) still marked at rest`);
|
|
325
325
|
}
|
|
326
326
|
return t;
|
|
327
|
-
},
|
|
327
|
+
}, be = (e, t) => {
|
|
328
328
|
let n = [], r = !1, i = window.visualViewport?.width ?? window.innerWidth ?? 0;
|
|
329
329
|
return e.forEach((e, t) => {
|
|
330
330
|
if (!(e instanceof HTMLElement) || !e.isConnected) return;
|
|
@@ -336,27 +336,27 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
336
336
|
if (o === "none") return;
|
|
337
337
|
let s = e.getAttribute(p) === "true", c = `screen[${t}]${s ? " (active)" : ""}`;
|
|
338
338
|
if (e.style.transform !== "" && e.style.transform !== "none" && n.push(`${c} transform=${e.style.transform}`), e.style.opacity !== "" && e.style.opacity !== "1" && n.push(`${c} opacity=${e.style.opacity}`), s && e.getAttribute("data-flemo-status") === "COMPLETED" && i > 0) {
|
|
339
|
-
let e =
|
|
339
|
+
let e = H(a);
|
|
340
340
|
e !== null && Math.abs(e) >= i * .5 && (r = !0);
|
|
341
341
|
}
|
|
342
342
|
}), {
|
|
343
343
|
residualInlineTransforms: n,
|
|
344
344
|
offViewportAtRest: r,
|
|
345
|
-
orphanedHolds:
|
|
345
|
+
orphanedHolds: U(t)
|
|
346
346
|
};
|
|
347
|
-
},
|
|
347
|
+
}, xe = E.map((e) => `[${b}="${e}"]`).join(","), Se = A(d), Ce = (e) => Math.round(e * 10) / 10, we = (e) => {
|
|
348
348
|
let t = e.getAttribute(x);
|
|
349
349
|
return t === null || t === "" ? null : t;
|
|
350
|
-
},
|
|
350
|
+
}, Te = (e) => {
|
|
351
351
|
let t = e.getAttribute(b);
|
|
352
352
|
return t !== null && E.includes(t);
|
|
353
|
-
},
|
|
353
|
+
}, Ee = () => {
|
|
354
354
|
try {
|
|
355
355
|
return document.querySelector("style[data-flemo-morph-sheet]")?.sheet?.cssRules.length ?? 0;
|
|
356
356
|
} catch {
|
|
357
357
|
return 0;
|
|
358
358
|
}
|
|
359
|
-
},
|
|
359
|
+
}, De = (e) => {
|
|
360
360
|
let t = {
|
|
361
361
|
registered: 0,
|
|
362
362
|
pairable: /* @__PURE__ */ new Set(),
|
|
@@ -366,17 +366,17 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
366
366
|
ghosts: 0,
|
|
367
367
|
ghostBornAt: /* @__PURE__ */ new Map(),
|
|
368
368
|
shortestGhostLifeMs: null,
|
|
369
|
-
sheetRulesAtStart:
|
|
369
|
+
sheetRulesAtStart: Ee()
|
|
370
370
|
}, n = new Set(e), r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map();
|
|
371
371
|
for (let e of Array.from(document.querySelectorAll(A(b)))) {
|
|
372
372
|
t.registered += 1;
|
|
373
|
-
let a =
|
|
373
|
+
let a = we(e);
|
|
374
374
|
if (a === null) continue;
|
|
375
|
-
if (
|
|
375
|
+
if (Te(e)) {
|
|
376
376
|
t.flew.add(a);
|
|
377
377
|
continue;
|
|
378
378
|
}
|
|
379
|
-
let o = e.closest(
|
|
379
|
+
let o = e.closest(Se);
|
|
380
380
|
if (o !== null && !n.has(o)) continue;
|
|
381
381
|
let s = o, c = r.get(a);
|
|
382
382
|
c || r.set(a, c = /* @__PURE__ */ new Set()), c.add(s);
|
|
@@ -389,27 +389,27 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
389
389
|
r && [...r.values()].some((e) => e > 1) && t.duplicated.add(e);
|
|
390
390
|
}
|
|
391
391
|
return t;
|
|
392
|
-
},
|
|
393
|
-
if (t.hasAttribute("data-flemo-morph-camera") && (e.camera = !0), !
|
|
394
|
-
let n =
|
|
392
|
+
}, Oe = (e, t) => {
|
|
393
|
+
if (t.hasAttribute("data-flemo-morph-camera") && (e.camera = !0), !Te(t)) return;
|
|
394
|
+
let n = we(t);
|
|
395
395
|
n !== null && e.flew.add(n);
|
|
396
|
-
},
|
|
397
|
-
for (let r of Array.from(t.addedNodes)) if (r instanceof Element) for (let t of
|
|
398
|
-
for (let r of Array.from(t.removedNodes)) if (r instanceof Element) for (let t of
|
|
396
|
+
}, ke = (e, t, n) => {
|
|
397
|
+
for (let r of Array.from(t.addedNodes)) if (r instanceof Element) for (let t of Ae(r)) e.ghostBornAt.has(t) || (e.ghosts += 1, e.ghostBornAt.set(t, n));
|
|
398
|
+
for (let r of Array.from(t.removedNodes)) if (r instanceof Element) for (let t of Ae(r)) {
|
|
399
399
|
let r = e.ghostBornAt.get(t);
|
|
400
400
|
if (r === void 0) continue;
|
|
401
401
|
e.ghostBornAt.delete(t);
|
|
402
402
|
let i = n - r;
|
|
403
403
|
(e.shortestGhostLifeMs === null || i < e.shortestGhostLifeMs) && (e.shortestGhostLifeMs = i);
|
|
404
404
|
}
|
|
405
|
-
},
|
|
405
|
+
}, Ae = (e) => [...e.hasAttribute("data-flemo-morph-ghost") ? [e] : [], ...Array.from(e.querySelectorAll(A(w)))], je = (e) => {
|
|
406
406
|
let t = e.shortestGhostLifeMs;
|
|
407
407
|
return t === null || t >= 34 ? [] : [{
|
|
408
408
|
kind: "ghost-cut",
|
|
409
|
-
atMs:
|
|
410
|
-
detail: `a morph ghost was removed ${
|
|
409
|
+
atMs: Ce(t),
|
|
410
|
+
detail: `a morph ghost was removed ${Ce(t)}ms after it was created (under one frame) — the departing content it stands for was never presented; this is the first-frame blade signature`
|
|
411
411
|
}];
|
|
412
|
-
},
|
|
412
|
+
}, Me = (e, t) => {
|
|
413
413
|
let n = [...e.pairable].sort(), r = [...e.flew].sort(), i = new Set(r), a = t ? {
|
|
414
414
|
strandedRoles: 0,
|
|
415
415
|
strandedStandIns: 0,
|
|
@@ -417,11 +417,11 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
417
417
|
layerResidue: 0,
|
|
418
418
|
leaked: 0
|
|
419
419
|
} : {
|
|
420
|
-
strandedRoles: document.querySelectorAll(
|
|
420
|
+
strandedRoles: document.querySelectorAll(xe).length,
|
|
421
421
|
strandedStandIns: document.querySelectorAll(A(C)).length,
|
|
422
422
|
strandedGhosts: document.querySelectorAll(A(w)).length,
|
|
423
423
|
layerResidue: Array.from(document.querySelectorAll(A(S))).reduce((e, t) => e + t.childElementCount, 0),
|
|
424
|
-
leaked: Math.max(0,
|
|
424
|
+
leaked: Math.max(0, Ee() - e.sheetRulesAtStart)
|
|
425
425
|
};
|
|
426
426
|
return {
|
|
427
427
|
registered: e.registered,
|
|
@@ -437,7 +437,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
437
437
|
layerResidue: a.layerResidue,
|
|
438
438
|
duplicatedKeys: [...e.duplicated].sort()
|
|
439
439
|
};
|
|
440
|
-
},
|
|
440
|
+
}, Ne = "flemo:devtools-panel-height", Pe = [{
|
|
441
441
|
key: "flemo:devtools",
|
|
442
442
|
storage: "session",
|
|
443
443
|
kind: "opt-in-diagnostic",
|
|
@@ -445,13 +445,13 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
445
445
|
fallback: "off",
|
|
446
446
|
effect: "arms this flight recorder in the playground (?devtools=on)"
|
|
447
447
|
}, {
|
|
448
|
-
key:
|
|
448
|
+
key: Ne,
|
|
449
449
|
storage: "session",
|
|
450
450
|
kind: "production-state",
|
|
451
451
|
values: "a pixel height",
|
|
452
452
|
fallback: "(the panel's default height)",
|
|
453
453
|
effect: "the drawer height this panel was last dragged to"
|
|
454
|
-
}], Fe = [],
|
|
454
|
+
}], Fe = [], Ie = [...Fe, ...Pe], W = [
|
|
455
455
|
{
|
|
456
456
|
key: "flemo:sixty",
|
|
457
457
|
storage: "session",
|
|
@@ -572,53 +572,53 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
572
572
|
storage: "session",
|
|
573
573
|
retiredWith: "the Low Power Mode release-latency probe (2026-08-22)"
|
|
574
574
|
}
|
|
575
|
-
],
|
|
575
|
+
], Le = "(retired — the library no longer reads this)", Re = (e) => {
|
|
576
576
|
try {
|
|
577
577
|
let t = e === "session" ? sessionStorage : localStorage;
|
|
578
578
|
return t.length, t;
|
|
579
579
|
} catch {
|
|
580
580
|
return null;
|
|
581
581
|
}
|
|
582
|
-
},
|
|
582
|
+
}, ze = (e, t) => {
|
|
583
583
|
try {
|
|
584
584
|
return e ? e.getItem(t) : null;
|
|
585
585
|
} catch {
|
|
586
586
|
return null;
|
|
587
587
|
}
|
|
588
|
-
},
|
|
589
|
-
let e = {}, t =
|
|
590
|
-
for (let r of
|
|
591
|
-
let i =
|
|
588
|
+
}, Be = new Set(Ie.map((e) => e.key)), Ve = new Set(W.map((e) => e.key)), He = () => {
|
|
589
|
+
let e = {}, t = Re("session"), n = Re("local");
|
|
590
|
+
for (let r of Ie) {
|
|
591
|
+
let i = ze(r.storage === "session" ? t : n, r.key);
|
|
592
592
|
i !== null && (e[r.key] = i);
|
|
593
593
|
}
|
|
594
|
-
for (let r of
|
|
595
|
-
let t =
|
|
596
|
-
t !== null && (e[`${r.key} (${a}) ${
|
|
594
|
+
for (let r of W) for (let [i, a] of [[t, "sessionStorage"], [n, "localStorage"]]) {
|
|
595
|
+
let t = ze(i, r.key);
|
|
596
|
+
t !== null && (e[`${r.key} (${a}) ${Le}`] = t);
|
|
597
597
|
}
|
|
598
598
|
for (let [r, i] of [[t, "sessionStorage"], [n, "localStorage"]]) if (r) try {
|
|
599
599
|
for (let t = 0; t < r.length; t += 1) {
|
|
600
600
|
let n = r.key(t);
|
|
601
|
-
!n || !n.startsWith("flemo:") ||
|
|
601
|
+
!n || !n.startsWith("flemo:") || Be.has(n) || Ve.has(n) || (e[`${n} (${i}, unknown key)`] = r.getItem(n) ?? "");
|
|
602
602
|
}
|
|
603
603
|
} catch {}
|
|
604
604
|
return e;
|
|
605
|
-
},
|
|
605
|
+
}, Ue = (e) => {
|
|
606
606
|
let t = [];
|
|
607
607
|
for (let [n, r] of Object.entries(e)) if (n.includes("(retired — the library no longer reads this)")) {
|
|
608
|
-
let e = n.slice(0, n.indexOf(" (")), i =
|
|
608
|
+
let e = n.slice(0, n.indexOf(" (")), i = W.find((t) => t.key === e);
|
|
609
609
|
t.push(`${n}=${r} — RETIRED residue: this key went with ${i?.retiredWith ?? "a removed feature"}. The library never reads it, so it cannot explain anything you are seeing. Safe to delete; it is listed only so it does not read as an unexplained lead.`);
|
|
610
610
|
continue;
|
|
611
611
|
}
|
|
612
612
|
return t;
|
|
613
|
-
},
|
|
613
|
+
}, We = "flemo:devtools-trace", Ge = () => {
|
|
614
614
|
try {
|
|
615
615
|
let e = sessionStorage;
|
|
616
616
|
return e.length, e;
|
|
617
617
|
} catch {
|
|
618
618
|
return null;
|
|
619
619
|
}
|
|
620
|
-
},
|
|
621
|
-
let n =
|
|
620
|
+
}, Ke = (e, t) => {
|
|
621
|
+
let n = Ge();
|
|
622
622
|
if (!n) return;
|
|
623
623
|
let r = e.slice(-10);
|
|
624
624
|
for (; r.length > 0;) {
|
|
@@ -629,23 +629,23 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
629
629
|
});
|
|
630
630
|
if (e.length <= 64e3) {
|
|
631
631
|
try {
|
|
632
|
-
n.setItem(
|
|
632
|
+
n.setItem(We, e);
|
|
633
633
|
} catch {}
|
|
634
634
|
return;
|
|
635
635
|
}
|
|
636
636
|
r = r.slice(1);
|
|
637
637
|
}
|
|
638
|
-
|
|
639
|
-
},
|
|
638
|
+
qe();
|
|
639
|
+
}, qe = () => {
|
|
640
640
|
try {
|
|
641
|
-
|
|
641
|
+
Ge()?.removeItem(We);
|
|
642
642
|
} catch {}
|
|
643
|
-
},
|
|
644
|
-
let t =
|
|
643
|
+
}, Je = (e) => {
|
|
644
|
+
let t = Ge();
|
|
645
645
|
if (!t) return null;
|
|
646
646
|
let n = null;
|
|
647
647
|
try {
|
|
648
|
-
n = t.getItem(
|
|
648
|
+
n = t.getItem(We);
|
|
649
649
|
} catch {
|
|
650
650
|
return null;
|
|
651
651
|
}
|
|
@@ -654,14 +654,14 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
654
654
|
try {
|
|
655
655
|
r = JSON.parse(n);
|
|
656
656
|
} catch {
|
|
657
|
-
return
|
|
657
|
+
return qe(), null;
|
|
658
658
|
}
|
|
659
|
-
return !r || r.version !== e || !Array.isArray(r.flights) ? (
|
|
659
|
+
return !r || r.version !== e || !Array.isArray(r.flights) ? (qe(), null) : {
|
|
660
660
|
savedAt: typeof r.savedAt == "string" ? r.savedAt : "",
|
|
661
661
|
flights: r.flights,
|
|
662
662
|
note: "These flights were recorded by the page instance BEFORE the last full load. They are kept apart from the live ones because they may have come from a different build."
|
|
663
663
|
};
|
|
664
|
-
},
|
|
664
|
+
}, Ye = 12, Xe = 20, Ze = 40, Qe = 500, $e = 200, et = (e) => {
|
|
665
665
|
let t = e.rafCadence.medianGapMs;
|
|
666
666
|
if (t === null) return {
|
|
667
667
|
id: "display-cadence",
|
|
@@ -669,17 +669,17 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
669
669
|
detail: "the idle frame cadence could not be sampled, so the display's rate is unknown"
|
|
670
670
|
};
|
|
671
671
|
let n = { medianIdleFrameMs: t };
|
|
672
|
-
return t <
|
|
672
|
+
return t < Ye ? {
|
|
673
673
|
id: "display-cadence",
|
|
674
674
|
status: "ok",
|
|
675
675
|
detail: `idle frames arrive every ${t}ms — a display above 60Hz. Frame budgets in this report are still quoted against 60Hz (a gap of 30ms or more)`,
|
|
676
676
|
metrics: n
|
|
677
|
-
} : t <=
|
|
677
|
+
} : t <= Xe ? {
|
|
678
678
|
id: "display-cadence",
|
|
679
679
|
status: "ok",
|
|
680
680
|
detail: `idle frames arrive every ${t}ms — a 60Hz clock`,
|
|
681
681
|
metrics: n
|
|
682
|
-
} : t <=
|
|
682
|
+
} : t <= Ze ? {
|
|
683
683
|
id: "display-cadence",
|
|
684
684
|
status: "violated",
|
|
685
685
|
detail: `idle frames arrive every ${t}ms — the page is being served roughly HALF rate. On iOS this is Low Power Mode, whose main-thread ceiling is ~30Hz while the compositor keeps 60: motion judged here is judged against a clock no transition can beat, and the ceiling is not a library defect. Turn it off, or judge elsewhere`,
|
|
@@ -690,7 +690,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
690
690
|
detail: `idle frames arrive every ${t}ms — the page is barely being served frames at all while idle. Something outside the transition owns this machine; no motion verdict taken here means anything`,
|
|
691
691
|
metrics: n
|
|
692
692
|
};
|
|
693
|
-
},
|
|
693
|
+
}, tt = (e) => {
|
|
694
694
|
if (!e.environment.observation.longTasks) return {
|
|
695
695
|
id: "machine-idle",
|
|
696
696
|
status: "unknown",
|
|
@@ -701,7 +701,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
701
701
|
idleLongTaskMs: n,
|
|
702
702
|
worstIdleTaskMs: r
|
|
703
703
|
};
|
|
704
|
-
return n >=
|
|
704
|
+
return n >= Qe || r >= $e ? {
|
|
705
705
|
id: "machine-idle",
|
|
706
706
|
status: "violated",
|
|
707
707
|
detail: `${t} long task(s) totalling ${n}ms ran while NO navigation was in flight (worst ${r}ms). Something else on this page or this machine was busy, and a motion verdict taken under someone else's load measures the load. A whole tremble campaign was invalidated by exactly this, with a build running in another window`,
|
|
@@ -712,7 +712,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
712
712
|
detail: `${t} idle long task(s), ${n}ms total — the page was quiet between navigations`,
|
|
713
713
|
metrics: i
|
|
714
714
|
};
|
|
715
|
-
},
|
|
715
|
+
}, nt = (e) => {
|
|
716
716
|
let { trusted: t, synthetic: n, pointerTypes: r } = e.input;
|
|
717
717
|
return n > 0 ? {
|
|
718
718
|
id: "real-input",
|
|
@@ -739,7 +739,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
739
739
|
synthetic: n
|
|
740
740
|
}
|
|
741
741
|
};
|
|
742
|
-
},
|
|
742
|
+
}, rt = (e) => e.input.pointerTypes.includes("touch") ? {
|
|
743
743
|
id: "touch-path",
|
|
744
744
|
status: "ok",
|
|
745
745
|
detail: "at least one navigation was driven by touch"
|
|
@@ -751,7 +751,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
751
751
|
id: "touch-path",
|
|
752
752
|
status: "unknown",
|
|
753
753
|
detail: "no touch-driven navigation was recorded on a touch-capable device. The swipe and pointer-capture paths are only reached by a finger; a build that had broken them outright once passed every automated layer green because every probe used a mouse"
|
|
754
|
-
},
|
|
754
|
+
}, it = [
|
|
755
755
|
{
|
|
756
756
|
id: "devtools-closed",
|
|
757
757
|
status: "unknown",
|
|
@@ -767,7 +767,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
767
767
|
status: "unknown",
|
|
768
768
|
detail: "which physical display this window is on, its refresh rate and scaling, cannot be read from the page. Establish it with the user before believing any verdict"
|
|
769
769
|
}
|
|
770
|
-
],
|
|
770
|
+
], at = (e) => {
|
|
771
771
|
let { environment: t } = e, n = [];
|
|
772
772
|
return n.push(t.emulationSuspected ? {
|
|
773
773
|
id: "device-emulation",
|
|
@@ -777,7 +777,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
777
777
|
id: "device-emulation",
|
|
778
778
|
status: "ok",
|
|
779
779
|
detail: "no device-emulation signature on this session"
|
|
780
|
-
}), n.push(
|
|
780
|
+
}), n.push(et(t)), n.push(e.documentHidden || e.wentHidden ? {
|
|
781
781
|
id: "page-foreground",
|
|
782
782
|
status: "violated",
|
|
783
783
|
detail: e.documentHidden ? "this document is HIDDEN right now — a backgrounded page is throttled to a fraction of its frames" : "this document was hidden at least once while recording; any flight that ran then was throttled"
|
|
@@ -785,7 +785,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
785
785
|
id: "page-foreground",
|
|
786
786
|
status: "ok",
|
|
787
787
|
detail: "the document stayed visible throughout"
|
|
788
|
-
}), n.push(
|
|
788
|
+
}), n.push(tt(e)), n.push(t.developmentHints.length > 0 ? {
|
|
789
789
|
id: "build-mode",
|
|
790
790
|
status: "violated",
|
|
791
791
|
detail: `development-server globals are present (${t.developmentHints.join(", ")}). A development build is a different program: unminified, double-invoking, and hot-reload instrumented. A day of ladder measurements once turned out to be measuring the build itself`
|
|
@@ -793,7 +793,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
793
793
|
id: "build-mode",
|
|
794
794
|
status: "unknown",
|
|
795
795
|
detail: "no development-server global was found. That is consistent with a production build but does not prove one — confirm how this page was built"
|
|
796
|
-
}), n.push(
|
|
796
|
+
}), n.push(nt(e)), n.push(rt(e)), n.push(t.reducedMotion ? {
|
|
797
797
|
id: "reduced-motion",
|
|
798
798
|
status: "violated",
|
|
799
799
|
detail: "this session prefers reduced motion, so the transitions under test are being suppressed or shortened. Whatever is on screen is not the motion being judged"
|
|
@@ -801,8 +801,8 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
801
801
|
id: "reduced-motion",
|
|
802
802
|
status: "ok",
|
|
803
803
|
detail: "reduced motion is not requested"
|
|
804
|
-
}), [...n, ...
|
|
805
|
-
},
|
|
804
|
+
}), [...n, ...it];
|
|
805
|
+
}, ot = 2e3, st = 40, ct = (e) => Math.round(e * 10) / 10, lt = (e) => typeof e.animationName == "string" && e.animationName.startsWith("flemo-"), ut = (e) => e instanceof Element ? `<${e.tagName.toLowerCase()}>${e.getAttribute("data-flemo-screen") === null ? "" : " (screen)"}` : "an unidentified node", dt = (e) => {
|
|
806
806
|
if (typeof document > "u") return {
|
|
807
807
|
detach: () => {},
|
|
808
808
|
sawAnimationEvent: () => !1,
|
|
@@ -813,18 +813,18 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
813
813
|
})
|
|
814
814
|
};
|
|
815
815
|
let t = [], n = !1, r = (t) => {
|
|
816
|
-
|
|
816
|
+
lt(t) && (n = !0, e.onAnimationStart(performance.now()));
|
|
817
817
|
}, i = (t) => {
|
|
818
|
-
|
|
818
|
+
lt(t) && (n = !0, e.onHit({
|
|
819
819
|
kind: "animation-cancel",
|
|
820
820
|
atMs: performance.now(),
|
|
821
|
-
detail: `${t.animationName} was CANCELLED on ${
|
|
821
|
+
detail: `${t.animationName} was CANCELLED on ${ut(t.target)} — the element was re-parented, re-styled or removed mid-flight. A cancelled animation loses its start time, and whatever restarts it is free to overwrite the authored delay`
|
|
822
822
|
}));
|
|
823
823
|
}, a = (t) => {
|
|
824
|
-
|
|
824
|
+
lt(t) && (n = !0, t.elapsedTime === 0 && e.onHit({
|
|
825
825
|
kind: "zero-length-animation-end",
|
|
826
826
|
atMs: performance.now(),
|
|
827
|
-
detail: `${t.animationName} reported animationend with elapsedTime 0 on ${
|
|
827
|
+
detail: `${t.animationName} reported animationend with elapsedTime 0 on ${ut(t.target)} — the animation ended without ever running. Anything landing on this event lands before the motion it was waiting for`
|
|
828
828
|
}));
|
|
829
829
|
}, o = (e) => {
|
|
830
830
|
let n = e.pointerType ?? "";
|
|
@@ -832,7 +832,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
832
832
|
atMs: performance.now(),
|
|
833
833
|
trusted: e.isTrusted === !0,
|
|
834
834
|
pointerType: n === "" ? e.type : n
|
|
835
|
-
}), t.length >
|
|
835
|
+
}), t.length > st && t.splice(0, t.length - st);
|
|
836
836
|
}, s = {
|
|
837
837
|
capture: !0,
|
|
838
838
|
passive: !0
|
|
@@ -843,7 +843,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
843
843
|
},
|
|
844
844
|
sawAnimationEvent: () => n,
|
|
845
845
|
inputBetween: (e, n) => {
|
|
846
|
-
let r = e -
|
|
846
|
+
let r = e - ot, i = t.filter((e) => e.atMs >= r && e.atMs <= n), a = i.filter((e) => e.trusted).length, o = new Set(i.map((e) => e.pointerType));
|
|
847
847
|
return {
|
|
848
848
|
trusted: a,
|
|
849
849
|
synthetic: i.length - a,
|
|
@@ -851,22 +851,22 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
851
851
|
};
|
|
852
852
|
}
|
|
853
853
|
};
|
|
854
|
-
},
|
|
854
|
+
}, ft = (e, t) => ({
|
|
855
855
|
kind: e.kind,
|
|
856
|
-
atMs:
|
|
856
|
+
atMs: ct(e.atMs - t),
|
|
857
857
|
detail: e.detail
|
|
858
|
-
}),
|
|
858
|
+
}), pt = (e) => {
|
|
859
859
|
/* v8 ignore next -- unreachable: deriveVerdict returns before this on an
|
|
860
860
|
empty flight list, so nothing ever asks for the median of nothing. */
|
|
861
861
|
if (e.length === 0) return 0;
|
|
862
862
|
let t = [...e].sort((e, t) => e - t);
|
|
863
863
|
return t[Math.floor(t.length / 2)];
|
|
864
|
-
},
|
|
864
|
+
}, mt = (e) => {
|
|
865
865
|
let t = [], n = e.preconditions.filter((e) => e.status === "violated");
|
|
866
866
|
if (n.length > 0 && t.push(`NOT EVIDENCE: ${n.length} judging precondition(s) failed — ${n.map((e) => e.id).join(", ")}. Everything below was measured under those conditions; fix them and measure again before drawing a conclusion from it.`), e.flights.length === 0) return t.push("No flights were recorded. Either no navigation happened while the recorder was attached, or it attached after the one you meant to measure — the recorder only sees flights that start after it does."), t;
|
|
867
867
|
e.observation.animationEvents || t.push("The animation channel observed NOTHING across this whole session: not one flemo keyframe reported a start, an end or a cancel, though flights were recorded. Treat every animation-derived field here as unmeasured rather than as clean — a probe that never fires reads exactly like a page with nothing to report.");
|
|
868
868
|
let r = e.flights, i = r.reduce((e, t) => Math.max(e, t.frameSamples.released.maxGapMs), 0), a = r.filter((e) => e.anomalies.length > 0).length;
|
|
869
|
-
t.push(`${r.length} flight(s) recorded. Median duration ${
|
|
869
|
+
t.push(`${r.length} flight(s) recorded. Median duration ${pt(r.map((e) => e.durationMs))}ms, worst frame gap during visible motion ${i}ms, ${a} flight(s) carrying at least one anomaly.`);
|
|
870
870
|
let o = r.filter((e) => e.motion.longestStallMs >= 48);
|
|
871
871
|
o.length > 0 && t.push(`${o.length} flight(s) STOPPED MOVING mid-flight (longest ${Math.max(...o.map((e) => e.motion.longestStallMs))}ms). Frames kept arriving; the picture did not change. Look at the hold and the animation's play state, not at the frame budget.`);
|
|
872
872
|
let s = r.filter((e) => e.morphs.skipped.length > 0);
|
|
@@ -882,7 +882,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
882
882
|
t.push(`${l.length} tripwire hit(s) across the session (${e.join(", ")}). These are one-frame events reported by the browser itself, not sampled — read the flights' \`tripwires\` arrays for the exact animations.`);
|
|
883
883
|
}
|
|
884
884
|
return r.filter((e) => e.frameSamples.released.over30Count > 0).length === 0 && a === 0 && n.length === 0 && t.push("No flight dropped a frame during visible motion (nothing at or over 30ms) and no anomaly fired. Under the preconditions above, this session is clean — what remains is in `blindSpots`, and none of it is reachable from page code."), t;
|
|
885
|
-
},
|
|
885
|
+
}, ht = "3", gt = new Set(O), _t = new Set(k), vt = A(d), yt = 2e3, bt = 1e3, xt = 4e3, G = (e) => Math.round(e * 10) / 10, St = null, Ct = () => ({
|
|
886
886
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
887
887
|
version: "3",
|
|
888
888
|
verdict: ["No DOM was available, so nothing could be observed. The recorder ran inert."],
|
|
@@ -901,14 +901,14 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
901
901
|
anomalies: [],
|
|
902
902
|
blindSpots: [...c],
|
|
903
903
|
judgingProtocol: [...ge]
|
|
904
|
-
}),
|
|
905
|
-
if (
|
|
904
|
+
}), wt = (e = {}) => {
|
|
905
|
+
if (St) return St;
|
|
906
906
|
if (typeof window > "u" || typeof document > "u") return {
|
|
907
907
|
detach: () => {},
|
|
908
|
-
report:
|
|
908
|
+
report: Ct,
|
|
909
909
|
mark: () => null
|
|
910
910
|
};
|
|
911
|
-
let n = e.maxFlights ?? 50, r = e.log ?? !1, i = e.installGlobal ?? !0, a = e.persist ?? !0, l =
|
|
911
|
+
let n = e.maxFlights ?? 50, r = e.log ?? !1, i = e.installGlobal ?? !0, a = e.persist ?? !0, l = He(), d = performance.now(), h = a ? Je("3") : null, g = {
|
|
912
912
|
medianGapMs: null,
|
|
913
913
|
sampleCount: 0
|
|
914
914
|
};
|
|
@@ -919,10 +919,10 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
919
919
|
try {
|
|
920
920
|
typeof PerformanceObserver < "u" && PerformanceObserver.supportedEntryTypes?.includes("longtask") && (S = new PerformanceObserver((e) => {
|
|
921
921
|
for (let t of e.getEntries()) x.push({
|
|
922
|
-
startMs:
|
|
923
|
-
durationMs:
|
|
922
|
+
startMs: G(t.startTime),
|
|
923
|
+
durationMs: G(t.duration)
|
|
924
924
|
});
|
|
925
|
-
x.length >
|
|
925
|
+
x.length > bt && x.splice(0, x.length - bt);
|
|
926
926
|
}), S.observe({
|
|
927
927
|
type: "longtask",
|
|
928
928
|
buffered: !0
|
|
@@ -930,40 +930,40 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
930
930
|
} catch {
|
|
931
931
|
S = null;
|
|
932
932
|
}
|
|
933
|
-
let C = [], w = 0, E = null, D = null, O = [], k = !1, j = !1, M = document.visibilityState === "hidden", N = 0, P = () => Array.from(document.querySelectorAll(
|
|
934
|
-
let t = Array.from(document.querySelectorAll(A(y))).filter((e) =>
|
|
933
|
+
let C = [], w = 0, E = null, D = null, O = [], k = !1, j = !1, M = document.visibilityState === "hidden", N = 0, P = () => Array.from(document.querySelectorAll(vt)).filter((e) => gt.has(e.getAttribute("data-flemo-status") ?? "")), te = () => E !== null || P().length > 0, F = (e) => {
|
|
934
|
+
let t = Array.from(document.querySelectorAll(A(y))).filter((e) => gt.has(e.getAttribute("data-flemo-bar-status") ?? "") || e.getAttribute("data-flemo-bar-riding") === "true").length, n = Array.from(document.querySelectorAll(A(v))).filter((e) => gt.has(e.getAttribute("data-flemo-status") ?? "")).length, r = Array.from(document.querySelectorAll(A(_))).filter((e) => gt.has(e.getAttribute("data-flemo-status") ?? "")).length;
|
|
935
935
|
return {
|
|
936
936
|
screens: e.length,
|
|
937
937
|
bars: t,
|
|
938
938
|
decorators: n,
|
|
939
939
|
parts: r
|
|
940
940
|
};
|
|
941
|
-
}, I =
|
|
941
|
+
}, I = dt({
|
|
942
942
|
onHit: (e) => {
|
|
943
943
|
let t = E;
|
|
944
|
-
t && t.tripwires.push(
|
|
944
|
+
t && t.tripwires.push(ft(e, t.t0Ms));
|
|
945
945
|
},
|
|
946
946
|
onAnimationStart: (e) => {
|
|
947
947
|
let t = E;
|
|
948
|
-
!t || t.firstAnimationAtMs !== null || (t.firstAnimationAtMs =
|
|
948
|
+
!t || t.firstAnimationAtMs !== null || (t.firstAnimationAtMs = G(e - t.t0Ms));
|
|
949
949
|
}
|
|
950
950
|
}), re = (e) => {
|
|
951
951
|
let t = /* @__PURE__ */ new Set();
|
|
952
952
|
for (let n of e.elements) {
|
|
953
953
|
let e = n.getAttribute("data-flemo-status") ?? "";
|
|
954
|
-
|
|
954
|
+
gt.has(e) && t.add(e);
|
|
955
955
|
}
|
|
956
956
|
return [...t];
|
|
957
957
|
}, L = () => {
|
|
958
958
|
let e = E;
|
|
959
959
|
if (!e || k) return;
|
|
960
960
|
let t = performance.now(), n = e.frames;
|
|
961
|
-
if (n.lastFrameAt !== null && n.heldGaps.length + n.releasedGaps.length <
|
|
961
|
+
if (n.lastFrameAt !== null && n.heldGaps.length + n.releasedGaps.length < yt) {
|
|
962
962
|
let r = t - n.lastFrameAt, i = oe(e.elements);
|
|
963
963
|
(i ? n.heldGaps : n.releasedGaps).push(r), i || (ce(n, e.elements, r), n.releasedFrames === 1 && me(e.images, e.elements));
|
|
964
964
|
}
|
|
965
|
-
if (n.lastFrameAt = t,
|
|
966
|
-
O = [...e.elements],
|
|
965
|
+
if (n.lastFrameAt = t, le(n, e.elements), t - e.t0Ms > 1e4) {
|
|
966
|
+
O = [...e.elements], de(t, re(e));
|
|
967
967
|
return;
|
|
968
968
|
}
|
|
969
969
|
e.rafId = requestAnimationFrame(L);
|
|
@@ -973,7 +973,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
973
973
|
let n = e.find((e) => e.getAttribute("data-flemo-active") === "true") ?? e[0], r = ye(n.getAttribute("data-flemo-status") ?? "") ?? "PUSH", i = null;
|
|
974
974
|
for (let t of e) {
|
|
975
975
|
let e = t.getAttribute(m);
|
|
976
|
-
if (e !== null &&
|
|
976
|
+
if (e !== null && _t.has(e)) {
|
|
977
977
|
i = e;
|
|
978
978
|
break;
|
|
979
979
|
}
|
|
@@ -992,10 +992,10 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
992
992
|
firstAnimationAtMs: null,
|
|
993
993
|
frames: ae(),
|
|
994
994
|
images: fe(e),
|
|
995
|
-
morphs:
|
|
995
|
+
morphs: De(e),
|
|
996
996
|
tripwires: [],
|
|
997
997
|
rafId: null
|
|
998
|
-
},
|
|
998
|
+
}, le(E.frames, E.elements), E.rafId = requestAnimationFrame(L);
|
|
999
999
|
}, se = (e, t) => {
|
|
1000
1000
|
let n = 2, r = () => {
|
|
1001
1001
|
if (k) return;
|
|
@@ -1003,35 +1003,35 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1003
1003
|
requestAnimationFrame(r);
|
|
1004
1004
|
return;
|
|
1005
1005
|
}
|
|
1006
|
-
let i =
|
|
1006
|
+
let i = be(t, te());
|
|
1007
1007
|
e.landing.residualInlineTransforms = i.residualInlineTransforms, e.landing.offViewportAtRest = i.offViewportAtRest, e.landing.orphanedHolds = i.orphanedHolds;
|
|
1008
1008
|
};
|
|
1009
1009
|
requestAnimationFrame(r);
|
|
1010
|
-
},
|
|
1010
|
+
}, R = (e, t) => {
|
|
1011
1011
|
let n = 2, r = () => {
|
|
1012
1012
|
if (!k) {
|
|
1013
1013
|
if (--n, n > 0) {
|
|
1014
1014
|
requestAnimationFrame(r);
|
|
1015
1015
|
return;
|
|
1016
1016
|
}
|
|
1017
|
-
e.morphs =
|
|
1017
|
+
e.morphs = Me(t.morphs, te());
|
|
1018
1018
|
}
|
|
1019
1019
|
};
|
|
1020
1020
|
requestAnimationFrame(r);
|
|
1021
|
-
},
|
|
1021
|
+
}, z = (e, t, n, r) => ({
|
|
1022
1022
|
id: r ? `${e.id} (in flight)` : e.id,
|
|
1023
1023
|
...e.routerId === void 0 ? {} : { routerId: e.routerId },
|
|
1024
1024
|
...e.bucket === null ? {} : { bucket: e.bucket },
|
|
1025
1025
|
kind: e.kind,
|
|
1026
1026
|
t0: {
|
|
1027
|
-
ms:
|
|
1027
|
+
ms: G(e.t0Ms),
|
|
1028
1028
|
iso: e.t0Iso
|
|
1029
1029
|
},
|
|
1030
1030
|
t1: {
|
|
1031
|
-
ms:
|
|
1031
|
+
ms: G(t),
|
|
1032
1032
|
iso: (/* @__PURE__ */ new Date()).toISOString()
|
|
1033
1033
|
},
|
|
1034
|
-
durationMs:
|
|
1034
|
+
durationMs: G(t - e.t0Ms),
|
|
1035
1035
|
driver: ve(e.frames.evidence),
|
|
1036
1036
|
participants: e.participants,
|
|
1037
1037
|
holds: {
|
|
@@ -1040,12 +1040,12 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1040
1040
|
},
|
|
1041
1041
|
frameSamples: _e(e.frames.heldGaps, e.frames.releasedGaps),
|
|
1042
1042
|
motion: {
|
|
1043
|
-
...
|
|
1043
|
+
...ue(e.frames),
|
|
1044
1044
|
firstAnimationAtMs: e.firstAnimationAtMs
|
|
1045
1045
|
},
|
|
1046
1046
|
images: he(e.images),
|
|
1047
|
-
morphs:
|
|
1048
|
-
tripwires: [...e.tripwires, ...
|
|
1047
|
+
morphs: Me(e.morphs, !0),
|
|
1048
|
+
tripwires: [...e.tripwires, ...je(e.morphs)],
|
|
1049
1049
|
input: I.inputBetween(e.t0Ms, t),
|
|
1050
1050
|
longTasks: [],
|
|
1051
1051
|
holdLongTasks: [],
|
|
@@ -1056,28 +1056,28 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1056
1056
|
orphanedHolds: []
|
|
1057
1057
|
},
|
|
1058
1058
|
anomalies: []
|
|
1059
|
-
}),
|
|
1059
|
+
}), de = (e, t) => {
|
|
1060
1060
|
let i = E;
|
|
1061
1061
|
/* v8 ignore next -- unreachable: both callers hold a flight. sampleFrame
|
|
1062
1062
|
returns at its own top when `current` is null, and evaluate only calls
|
|
1063
1063
|
this inside `if (current && ...)`. The narrowing stays for the type. */
|
|
1064
1064
|
if (!i) return;
|
|
1065
1065
|
me(i.images, i.elements), E = null, i.rafId !== null && cancelAnimationFrame(i.rafId);
|
|
1066
|
-
let a =
|
|
1067
|
-
C.push(a), C.length > n && C.splice(0, C.length - n), t.length === 0 && (se(a, i.elements),
|
|
1066
|
+
let a = z(i, e, t, !1);
|
|
1067
|
+
C.push(a), C.length > n && C.splice(0, C.length - n), t.length === 0 && (se(a, i.elements), R(a, i)), r && console.info(`[flemo devtools] ${a.id} ${a.kind} driver=${a.driver} ${a.durationMs}ms screens=${a.participants.screens}`);
|
|
1068
1068
|
}, B = (e) => {
|
|
1069
1069
|
let t = E;
|
|
1070
1070
|
if (!t || !(e.target instanceof Element)) return;
|
|
1071
1071
|
let n = e.target.getAttribute(m);
|
|
1072
|
-
if (n !== null &&
|
|
1073
|
-
let e =
|
|
1072
|
+
if (n !== null && _t.has(n) && t.holdKind === null && (t.holdKind = n), n !== null && _t.has(n) && t.holdReleasedAtMs !== null && t.frames.holdReassertedAtMs === null) {
|
|
1073
|
+
let e = G(performance.now() - t.t0Ms);
|
|
1074
1074
|
t.frames.holdReassertedAtMs = e, t.tripwires.push({
|
|
1075
1075
|
kind: "hold-reassert",
|
|
1076
1076
|
atMs: e,
|
|
1077
1077
|
detail: "an animation hold was re-asserted after this flight had already released it — the motion pauses here while every timing metric stays clean"
|
|
1078
1078
|
});
|
|
1079
1079
|
}
|
|
1080
|
-
(n === "false" || n === null) && e.oldValue !== null &&
|
|
1080
|
+
(n === "false" || n === null) && e.oldValue !== null && _t.has(e.oldValue) && t.holdReleasedAtMs === null && !oe(t.elements) && (t.holdReleasedAtMs = G(performance.now() - t.t0Ms));
|
|
1081
1081
|
}, V = () => {
|
|
1082
1082
|
let e = P();
|
|
1083
1083
|
if (O.length > 0) {
|
|
@@ -1089,17 +1089,17 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1089
1089
|
return;
|
|
1090
1090
|
}
|
|
1091
1091
|
if (E && e.length === 0) {
|
|
1092
|
-
|
|
1092
|
+
de(performance.now(), []);
|
|
1093
1093
|
return;
|
|
1094
1094
|
}
|
|
1095
1095
|
if (E) for (let t of e) E.elements.includes(t) || (E.elements.push(t), pe(E.images, E.elements, t.querySelectorAll("img")), E.participants = F(E.elements));
|
|
1096
|
-
},
|
|
1096
|
+
}, H = null, U = null, xe = () => {
|
|
1097
1097
|
let e = document.documentElement;
|
|
1098
1098
|
if (!e) return !1;
|
|
1099
1099
|
let t = new MutationObserver((e) => {
|
|
1100
1100
|
if (k) return;
|
|
1101
1101
|
let t = performance.now();
|
|
1102
|
-
for (let n of e) n.type === "attributes" ? n.attributeName === "data-flemo-anim-hold" ? B(n) : E && (n.attributeName === "data-flemo-morph" || n.attributeName === "data-flemo-morph-camera") && n.target instanceof Element &&
|
|
1102
|
+
for (let n of e) n.type === "attributes" ? n.attributeName === "data-flemo-anim-hold" ? B(n) : E && (n.attributeName === "data-flemo-morph" || n.attributeName === "data-flemo-morph-camera") && n.target instanceof Element && Oe(E.morphs, n.target) : (E && ke(E.morphs, n, t), E && n.addedNodes.length > 0 && pe(E.images, E.elements, n.addedNodes));
|
|
1103
1103
|
V();
|
|
1104
1104
|
});
|
|
1105
1105
|
try {
|
|
@@ -1119,30 +1119,30 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1119
1119
|
} catch {
|
|
1120
1120
|
return !1;
|
|
1121
1121
|
}
|
|
1122
|
-
return
|
|
1122
|
+
return H = t, V(), !0;
|
|
1123
1123
|
};
|
|
1124
|
-
if (!
|
|
1124
|
+
if (!xe()) {
|
|
1125
1125
|
let e = () => {
|
|
1126
|
-
|
|
1126
|
+
U = null, k || xe();
|
|
1127
1127
|
};
|
|
1128
|
-
|
|
1128
|
+
U = e, document.addEventListener("DOMContentLoaded", e, { once: !0 });
|
|
1129
1129
|
}
|
|
1130
|
-
let
|
|
1131
|
-
document.visibilityState === "hidden" && (M = !0, a && E === null &&
|
|
1130
|
+
let Se = () => {
|
|
1131
|
+
document.visibilityState === "hidden" && (M = !0, a && E === null && Ke(C, "3"));
|
|
1132
1132
|
};
|
|
1133
|
-
document.addEventListener("visibilitychange",
|
|
1134
|
-
let
|
|
1135
|
-
N = 0, !k && (E === null &&
|
|
1133
|
+
document.addEventListener("visibilitychange", Se);
|
|
1134
|
+
let Ce = () => {
|
|
1135
|
+
N = 0, !k && (E === null && Ke(C, "3"), N = window.setTimeout(Ce, xt));
|
|
1136
1136
|
};
|
|
1137
|
-
a && (N = window.setTimeout(
|
|
1138
|
-
let
|
|
1137
|
+
a && (N = window.setTimeout(Ce, xt));
|
|
1138
|
+
let we = (e) => {
|
|
1139
1139
|
let t = x.filter((t) => t.startMs + t.durationMs >= e.t0.ms - 120 && t.startMs <= e.t1.ms), n = e.holds.kind === null ? e.t0.ms : e.holds.releasedAtMs === null ? e.t1.ms : e.t0.ms + e.holds.releasedAtMs;
|
|
1140
1140
|
return {
|
|
1141
1141
|
released: t.filter((e) => e.startMs + e.durationMs > n),
|
|
1142
1142
|
held: t.filter((e) => e.startMs + e.durationMs <= n)
|
|
1143
1143
|
};
|
|
1144
|
-
},
|
|
1145
|
-
let t =
|
|
1144
|
+
}, Te = (e) => x.filter((t) => t.startMs >= d && !e.some((e) => t.startMs + t.durationMs >= e.t0.ms && t.startMs <= e.t1.ms)), Ee = (e) => {
|
|
1145
|
+
let t = we(e), n = {
|
|
1146
1146
|
...e,
|
|
1147
1147
|
longTasks: t.released,
|
|
1148
1148
|
holdLongTasks: t.held,
|
|
@@ -1169,12 +1169,12 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1169
1169
|
morphs: n.morphs,
|
|
1170
1170
|
tripwires: n.tripwires
|
|
1171
1171
|
}), n;
|
|
1172
|
-
},
|
|
1173
|
-
let e = C.map(
|
|
1172
|
+
}, Ae = () => {
|
|
1173
|
+
let e = C.map(Ee), n = E;
|
|
1174
1174
|
if (!n) return e;
|
|
1175
1175
|
let r = performance.now(), i = r - n.t0Ms > t;
|
|
1176
|
-
return [...e,
|
|
1177
|
-
},
|
|
1176
|
+
return [...e, Ee(z(n, r, i ? re(n) : [], !0))];
|
|
1177
|
+
}, Ne = (e) => {
|
|
1178
1178
|
let t = /* @__PURE__ */ new Set(), n = 0, r = 0;
|
|
1179
1179
|
for (let i of e) {
|
|
1180
1180
|
n += i.input.trusted, r += i.input.synthetic;
|
|
@@ -1186,20 +1186,20 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1186
1186
|
pointerTypes: [...t].sort()
|
|
1187
1187
|
};
|
|
1188
1188
|
}, Pe = () => {
|
|
1189
|
-
let e =
|
|
1189
|
+
let e = He(), t = { ...e };
|
|
1190
1190
|
for (let [n, r] of Object.entries(l)) n in e || (t[`${n} (at attach, since cleared)`] = r);
|
|
1191
|
-
let n =
|
|
1191
|
+
let n = Ue(t), r = ne(g, I.sawAnimationEvent()), i = Ae(), a = E, o = at({
|
|
1192
1192
|
environment: r,
|
|
1193
|
-
idleLongTasks:
|
|
1193
|
+
idleLongTasks: Te(i),
|
|
1194
1194
|
observedMs: performance.now() - d,
|
|
1195
1195
|
wentHidden: M,
|
|
1196
1196
|
documentHidden: document.visibilityState === "hidden",
|
|
1197
|
-
input:
|
|
1197
|
+
input: Ne(i)
|
|
1198
1198
|
});
|
|
1199
1199
|
return {
|
|
1200
1200
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1201
1201
|
version: "3",
|
|
1202
|
-
verdict:
|
|
1202
|
+
verdict: mt({
|
|
1203
1203
|
preconditions: o,
|
|
1204
1204
|
flights: i,
|
|
1205
1205
|
observation: r.observation
|
|
@@ -1222,16 +1222,16 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1222
1222
|
blindSpots: [...c],
|
|
1223
1223
|
judgingProtocol: [...ge]
|
|
1224
1224
|
};
|
|
1225
|
-
}, Fe = (e) => (D = e === null || e === "" ? null : e, D),
|
|
1225
|
+
}, Fe = (e) => (D = e === null || e === "" ? null : e, D), Ie = () => {
|
|
1226
1226
|
if (!k) {
|
|
1227
|
-
if (k = !0,
|
|
1227
|
+
if (k = !0, H?.disconnect(), U !== null && (document.removeEventListener("DOMContentLoaded", U), U = null), document.removeEventListener("visibilitychange", Se), I.detach(), S?.disconnect(), window.clearTimeout(N), N = 0, E?.rafId != null && cancelAnimationFrame(E.rafId), E = null, j) {
|
|
1228
1228
|
let e = window;
|
|
1229
1229
|
e.flemo?.__flemoDevtools === !0 && delete e.flemo;
|
|
1230
1230
|
}
|
|
1231
|
-
|
|
1231
|
+
St = null;
|
|
1232
1232
|
}
|
|
1233
|
-
},
|
|
1234
|
-
detach:
|
|
1233
|
+
}, W = {
|
|
1234
|
+
detach: Ie,
|
|
1235
1235
|
report: Pe,
|
|
1236
1236
|
mark: Fe
|
|
1237
1237
|
};
|
|
@@ -1240,13 +1240,13 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1240
1240
|
(t === void 0 || t?.__flemoDevtools === !0) && (e.flemo = {
|
|
1241
1241
|
__flemoDevtools: !0,
|
|
1242
1242
|
report: Pe,
|
|
1243
|
-
flights:
|
|
1243
|
+
flights: Ae,
|
|
1244
1244
|
mark: Fe,
|
|
1245
|
-
detach:
|
|
1245
|
+
detach: Ie
|
|
1246
1246
|
}, j = !0);
|
|
1247
1247
|
}
|
|
1248
|
-
return
|
|
1249
|
-
},
|
|
1248
|
+
return St = W, W;
|
|
1249
|
+
}, Tt = O.map((e) => A(d) + j(f, e)).join(","), Et = () => document.querySelector(Tt) !== null, Dt = (e) => {
|
|
1250
1250
|
let t = document.createElement("div");
|
|
1251
1251
|
t.setAttribute(D, ""), t.style.position = "fixed", t.style.top = "0", t.style.left = "0", t.style.width = "0", t.style.height = "0", t.style.zIndex = "2147483000";
|
|
1252
1252
|
let n = t.attachShadow({ mode: "open" }), r = document.createElement("style");
|
|
@@ -1256,7 +1256,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1256
1256
|
host: t,
|
|
1257
1257
|
root: i
|
|
1258
1258
|
};
|
|
1259
|
-
},
|
|
1259
|
+
}, Ot = () => {}, kt = (e) => {
|
|
1260
1260
|
if (e) return {
|
|
1261
1261
|
recorder: e,
|
|
1262
1262
|
ownsRecorder: !1
|
|
@@ -1265,184 +1265,184 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1265
1265
|
return t?.__flemoDevtools === !0 && typeof t.report == "function" ? {
|
|
1266
1266
|
recorder: {
|
|
1267
1267
|
report: t.report,
|
|
1268
|
-
detach:
|
|
1268
|
+
detach: Ot,
|
|
1269
1269
|
mark: t.mark ?? (() => null)
|
|
1270
1270
|
},
|
|
1271
1271
|
ownsRecorder: !1
|
|
1272
1272
|
} : {
|
|
1273
|
-
recorder:
|
|
1273
|
+
recorder: wt(),
|
|
1274
1274
|
ownsRecorder: !0
|
|
1275
1275
|
};
|
|
1276
|
-
},
|
|
1276
|
+
}, At = "http://www.w3.org/2000/svg", K = (e, t, n) => {
|
|
1277
1277
|
let r = document.createElement(e);
|
|
1278
1278
|
return t !== void 0 && (r.className = t), n !== void 0 && (r.textContent = n), r;
|
|
1279
|
-
},
|
|
1280
|
-
let n = document.createElementNS(
|
|
1279
|
+
}, jt = (e, t) => {
|
|
1280
|
+
let n = document.createElementNS(At, e);
|
|
1281
1281
|
for (let [e, r] of Object.entries(t)) n.setAttribute(e, r);
|
|
1282
1282
|
return n;
|
|
1283
|
-
},
|
|
1283
|
+
}, Mt = (e) => {
|
|
1284
1284
|
for (; e.firstChild !== null;) e.removeChild(e.firstChild);
|
|
1285
|
-
},
|
|
1285
|
+
}, Nt = (e, t) => {
|
|
1286
1286
|
e.textContent !== t && (e.textContent = t);
|
|
1287
|
-
},
|
|
1287
|
+
}, q = (e) => e == null || e === "" ? "—" : String(e), J = (e) => typeof e == "number" && Number.isFinite(e) ? `${Math.round(e)}ms` : "—", Pt = (e) => typeof e == "number" && Number.isFinite(e) ? `${Math.round(e * 10) / 10}ms` : "—", Y = (e) => typeof e == "number" && Number.isFinite(e) ? String(e) : "—", Ft = (e) => e === !0 ? "yes" : e === !1 ? "no" : "—", It = (e) => {
|
|
1288
1288
|
let t = e?.environment;
|
|
1289
1289
|
if (!t) return "—";
|
|
1290
1290
|
let n = t.viewport, r = n && typeof n.width == "number" && typeof n.height == "number" ? `${Math.round(n.width)}×${Math.round(n.height)}` : "—";
|
|
1291
1291
|
return [
|
|
1292
|
-
|
|
1293
|
-
`dpr ${
|
|
1292
|
+
q(t.engine),
|
|
1293
|
+
`dpr ${q(t.devicePixelRatio)}`,
|
|
1294
1294
|
r,
|
|
1295
|
-
`rAF ${
|
|
1295
|
+
`rAF ${Pt(t.rafCadence?.medianGapMs)}`
|
|
1296
1296
|
].join(" · ");
|
|
1297
|
-
},
|
|
1297
|
+
}, Lt = (e, t) => `${t ?? ""}#${e.map((e) => `${e?.id ?? ""}|${e?.kind ?? ""}|${e?.driver ?? ""}|${Math.round(e?.durationMs ?? 0)}|${e?.participants?.screens ?? 0}|${e?.anomalies?.length ?? 0}`).join(",")}`, Rt = (e) => {
|
|
1298
1298
|
let t = e?.released?.gaps;
|
|
1299
1299
|
if (!Array.isArray(t)) return null;
|
|
1300
1300
|
let n = t.filter((e) => typeof e == "number" && Number.isFinite(e));
|
|
1301
1301
|
return n.length >= 2 ? n : null;
|
|
1302
|
-
},
|
|
1303
|
-
let i =
|
|
1304
|
-
i.appendChild(
|
|
1305
|
-
},
|
|
1306
|
-
let n =
|
|
1307
|
-
return n.appendChild(
|
|
1308
|
-
},
|
|
1309
|
-
e.appendChild(
|
|
1310
|
-
},
|
|
1311
|
-
|
|
1312
|
-
for (let n of t?.verdict ?? []) e.appendChild(
|
|
1313
|
-
for (let n of t?.preconditions ?? []) n?.status === "violated" && e.appendChild(
|
|
1314
|
-
for (let n of t?.overrides?.warnings ?? []) e.appendChild(
|
|
1315
|
-
for (let n of t?.anomalies ?? []) e.appendChild(
|
|
1316
|
-
for (let [n, r] of Object.entries(t?.overrides?.active ?? {})) e.appendChild(
|
|
1317
|
-
},
|
|
1318
|
-
if (
|
|
1319
|
-
|
|
1302
|
+
}, zt = "\n:host {\n all: initial;\n color-scheme: dark;\n}\n* { box-sizing: border-box; }\n.root {\n --bg: #14161a;\n --bg-soft: #1b1e24;\n --line: #2b3038;\n --fg: #e6e9ef;\n --fg-dim: #99a1b0;\n --accent: #7cc4ff;\n --warn: #ffb454;\n --bad: #ff6b6b;\n font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n color: var(--fg);\n}\n@media (prefers-color-scheme: light) {\n .root {\n --bg: #ffffff;\n --bg-soft: #f4f6f9;\n --line: #dde1e8;\n --fg: #1a1d22;\n --fg-dim: #5c6472;\n --accent: #0b6bcb;\n --warn: #a35a00;\n --bad: #c2261f;\n }\n}\n.toggle {\n position: fixed;\n bottom: 12px;\n z-index: 2147483000;\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 0;\n padding: 6px 10px;\n border: 1px solid var(--line);\n border-radius: 999px;\n background: var(--bg);\n color: var(--fg);\n font: inherit;\n cursor: pointer;\n}\n.toggle:hover { background: var(--bg-soft); }\n.toggle[data-corner=\"bottom-right\"] { right: 12px; }\n.toggle[data-corner=\"bottom-left\"] { left: 12px; }\n.mark { font-weight: 700; letter-spacing: 0.04em; }\n.count {\n padding: 0 6px;\n border-radius: 999px;\n background: var(--bg-soft);\n color: var(--fg-dim);\n}\n.dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--bad);\n}\n.dot[hidden] { display: none; }\n.panel {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 2147482999;\n display: flex;\n flex-direction: column;\n max-width: 100%;\n border-top: 1px solid var(--line);\n background: var(--bg);\n overflow: hidden;\n}\n.panel[hidden] { display: none; }\n.grip {\n flex: 0 0 6px;\n height: 6px;\n background: var(--line);\n cursor: ns-resize;\n touch-action: none;\n}\n.head {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n border-bottom: 1px solid var(--line);\n}\n.env { color: var(--fg-dim); }\n.spacer { flex: 1 1 auto; }\n.act {\n padding: 4px 8px;\n border: 1px solid var(--line);\n border-radius: 4px;\n background: var(--bg-soft);\n color: var(--fg);\n font: inherit;\n cursor: pointer;\n}\n.chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n flex: 1 1 100%;\n}\n.chips:empty { display: none; }\n.chip {\n padding: 2px 8px;\n border: 1px solid var(--line);\n border-radius: 999px;\n background: var(--bg-soft);\n color: var(--fg-dim);\n max-width: 100%;\n overflow-wrap: anywhere;\n}\n/* The verdict reads as prose, not as a tag: it is a sentence about the whole\n session and it is the first thing anybody should read. */\n.chip.lead {\n border-color: var(--fg);\n color: var(--fg);\n white-space: normal;\n max-width: 100%;\n line-height: 1.5;\n}\n.chip.warn { border-color: var(--warn); color: var(--warn); }\n.chip.bad { border-color: var(--bad); color: var(--bad); }\n.body {\n display: flex;\n flex: 1 1 auto;\n min-height: 0;\n}\n.list {\n flex: 0 0 40%;\n max-width: 340px;\n min-width: 180px;\n overflow: auto;\n border-right: 1px solid var(--line);\n}\n.row {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 6px 10px;\n border: 0;\n border-bottom: 1px solid var(--line);\n background: none;\n color: var(--fg);\n font: inherit;\n text-align: left;\n cursor: pointer;\n}\n.row[aria-selected=\"true\"] { background: var(--bg-soft); }\n.row .kind { font-weight: 700; }\n.row .driver { color: var(--accent); }\n.row .dur, .row .screens { color: var(--fg-dim); }\n.row .n {\n margin-left: auto;\n padding: 0 6px;\n border-radius: 999px;\n background: var(--bg-soft);\n color: var(--fg-dim);\n}\n.row .n.bad { background: var(--bad); color: #fff; }\n.detail { flex: 1 1 auto; overflow: auto; padding: 8px 10px; }\n.section { margin: 0 0 10px; }\n.section > h2 {\n margin: 0 0 4px;\n font: inherit;\n font-weight: 700;\n color: var(--fg-dim);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n.kv { display: flex; gap: 8px; }\n.kv > .k { flex: 0 0 34%; max-width: 180px; color: var(--fg-dim); }\n.kv > .v { flex: 1 1 auto; overflow-wrap: anywhere; }\n/* A value that IS the finding — a stall, a re-asserted hold, an orphan. */\n.kv > .v.bad { color: var(--bad); }\n.li { overflow-wrap: anywhere; }\n.li.bad { color: var(--bad); }\n.dim { color: var(--fg-dim); }\n.spark { display: block; width: 100%; height: 28px; }\n.foot { border-top: 1px solid var(--line); padding: 6px 10px; color: var(--fg-dim); }\n.foot summary { cursor: pointer; }\n.foot .li { margin-top: 4px; }\n", Bt = 48, X = (e, t, n, r) => {
|
|
1303
|
+
let i = K("div", "kv");
|
|
1304
|
+
i.appendChild(K("span", "k", t)), i.appendChild(K("span", r ? `v ${r}` : "v", n)), e.appendChild(i);
|
|
1305
|
+
}, Z = (e, t) => {
|
|
1306
|
+
let n = K("section", "section");
|
|
1307
|
+
return n.appendChild(K("h2", void 0, t)), e.appendChild(n), n;
|
|
1308
|
+
}, Q = (e, t, n = "li") => {
|
|
1309
|
+
e.appendChild(K("div", n, t));
|
|
1310
|
+
}, Vt = (e, t) => {
|
|
1311
|
+
Mt(e);
|
|
1312
|
+
for (let n of t?.verdict ?? []) e.appendChild(K("span", "chip lead", q(n)));
|
|
1313
|
+
for (let n of t?.preconditions ?? []) n?.status === "violated" && e.appendChild(K("span", "chip bad", `${n.id}: ${q(n.detail)}`));
|
|
1314
|
+
for (let n of t?.overrides?.warnings ?? []) e.appendChild(K("span", "chip warn", q(n)));
|
|
1315
|
+
for (let n of t?.anomalies ?? []) e.appendChild(K("span", "chip bad", q(n)));
|
|
1316
|
+
for (let [n, r] of Object.entries(t?.overrides?.active ?? {})) e.appendChild(K("span", "chip", `${n}=${String(r)}`));
|
|
1317
|
+
}, Ht = (e, t, n, r) => {
|
|
1318
|
+
if (Mt(e), t.length === 0) {
|
|
1319
|
+
Q(e, "no flights recorded yet — navigate once", "li dim");
|
|
1320
1320
|
return;
|
|
1321
1321
|
}
|
|
1322
1322
|
for (let i = t.length - 1; i >= 0; --i) {
|
|
1323
|
-
let a = t[i], o =
|
|
1324
|
-
s.type = "button", s.setAttribute("data-flight-id", o), s.setAttribute("aria-selected", String(o === n)), s.appendChild(
|
|
1323
|
+
let a = t[i], o = q(a?.id), s = K("button", "row");
|
|
1324
|
+
s.type = "button", s.setAttribute("data-flight-id", o), s.setAttribute("aria-selected", String(o === n)), s.appendChild(K("span", "kind", q(a?.kind))), s.appendChild(K("span", "driver", q(a?.driver))), s.appendChild(K("span", "dur", J(a?.durationMs))), s.appendChild(K("span", "screens", `${Y(a?.participants?.screens)} scr`));
|
|
1325
1325
|
let c = a?.anomalies?.length ?? 0;
|
|
1326
|
-
s.appendChild(
|
|
1326
|
+
s.appendChild(K("span", c > 0 ? "n bad" : "n", String(c))), s.addEventListener("click", () => r(o)), e.appendChild(s);
|
|
1327
1327
|
}
|
|
1328
|
-
},
|
|
1328
|
+
}, Ut = (e, t, n) => {
|
|
1329
1329
|
if (!n) {
|
|
1330
|
-
|
|
1330
|
+
X(e, t, "—");
|
|
1331
1331
|
return;
|
|
1332
1332
|
}
|
|
1333
1333
|
let r = [
|
|
1334
|
-
`${
|
|
1335
|
-
`median ${
|
|
1336
|
-
`max ${
|
|
1334
|
+
`${Y(n.count)} frames`,
|
|
1335
|
+
`median ${Pt(n.medianGapMs)}`,
|
|
1336
|
+
`max ${Pt(n.maxGapMs)}`
|
|
1337
1337
|
];
|
|
1338
|
-
typeof n.over30Count == "number" && r.push(`>30ms ×${n.over30Count}`),
|
|
1339
|
-
},
|
|
1340
|
-
let t = Math.max(...e), n = t > 0 ? t : 1, r = 100 / (e.length - 1), i = e.map((e, t) => `${Math.round(t * r * 10) / 10},${Math.round((27 - e / n * 26) * 10) / 10}`).join(" "), a =
|
|
1338
|
+
typeof n.over30Count == "number" && r.push(`>30ms ×${n.over30Count}`), X(e, t, r.join(" · "));
|
|
1339
|
+
}, Wt = (e) => {
|
|
1340
|
+
let t = Math.max(...e), n = t > 0 ? t : 1, r = 100 / (e.length - 1), i = e.map((e, t) => `${Math.round(t * r * 10) / 10},${Math.round((27 - e / n * 26) * 10) / 10}`).join(" "), a = jt("svg", {
|
|
1341
1341
|
class: "spark",
|
|
1342
1342
|
viewBox: "0 0 100 28",
|
|
1343
1343
|
preserveAspectRatio: "none",
|
|
1344
1344
|
"aria-hidden": "true"
|
|
1345
1345
|
});
|
|
1346
|
-
return a.appendChild(
|
|
1346
|
+
return a.appendChild(jt("polyline", {
|
|
1347
1347
|
points: i,
|
|
1348
1348
|
fill: "none",
|
|
1349
1349
|
stroke: "currentColor",
|
|
1350
1350
|
"stroke-width": "1",
|
|
1351
1351
|
"vector-effect": "non-scaling-stroke"
|
|
1352
1352
|
})), a;
|
|
1353
|
-
},
|
|
1353
|
+
}, Gt = (e, t) => {
|
|
1354
1354
|
let n = t.longTasks ?? [], r = t.holdLongTasks ?? [];
|
|
1355
1355
|
if (n.length === 0 && r.length === 0) {
|
|
1356
|
-
|
|
1356
|
+
Q(e, "none", "li dim");
|
|
1357
1357
|
return;
|
|
1358
1358
|
}
|
|
1359
|
-
let i = (e) => `${
|
|
1360
|
-
for (let t of n)
|
|
1361
|
-
for (let t of r)
|
|
1362
|
-
},
|
|
1363
|
-
if (
|
|
1364
|
-
|
|
1359
|
+
let i = (e) => `${J(e?.startMs)} + ${J(e?.durationMs)}`;
|
|
1360
|
+
for (let t of n) Q(e, i(t), "li bad");
|
|
1361
|
+
for (let t of r) Q(e, `${i(t)} (absorbed by hold)`, "li dim");
|
|
1362
|
+
}, Kt = (e, t) => {
|
|
1363
|
+
if (Mt(e), !t) {
|
|
1364
|
+
Q(e, "select a flight", "li dim");
|
|
1365
1365
|
return;
|
|
1366
1366
|
}
|
|
1367
|
-
let n =
|
|
1368
|
-
|
|
1369
|
-
let r =
|
|
1370
|
-
|
|
1371
|
-
let i =
|
|
1372
|
-
i && r.appendChild(
|
|
1373
|
-
let a =
|
|
1374
|
-
|
|
1367
|
+
let n = Z(e, "timing");
|
|
1368
|
+
X(n, "id", q(t.id)), X(n, "kind / driver", `${q(t.kind)} · ${q(t.driver)}`), X(n, "router", q(t.routerId)), X(n, "t0", q(t.t0?.iso)), X(n, "duration", J(t.durationMs)), X(n, "participants", `${Y(t.participants?.screens)} screens · ${Y(t.participants?.bars)} bars · ${Y(t.participants?.decorators)} decorators · ${Y(t.participants?.parts)} parts`), X(n, "hold", `${q(t.holds?.kind)} · released ${J(t.holds?.releasedAtMs)}`);
|
|
1369
|
+
let r = Z(e, "frames");
|
|
1370
|
+
Ut(r, "held (absorbed)", t.frameSamples?.held), Ut(r, "released (visible)", t.frameSamples?.released);
|
|
1371
|
+
let i = Rt(t.frameSamples);
|
|
1372
|
+
i && r.appendChild(Wt(i));
|
|
1373
|
+
let a = Z(e, "motion (did it move)"), o = t.motion?.longestStallMs, s = t.motion?.holdReassertedAtMs;
|
|
1374
|
+
X(a, "released frames", Y(t.motion?.sampledFrames)), X(a, "stalled frames", Y(t.motion?.stalledFrames), (t.motion?.stalledFrames ?? 0) > 0 ? "bad" : void 0), X(a, "longest stall", J(o), (o ?? 0) >= Bt ? "bad" : void 0), X(a, "paused after release", Ft(t.motion?.pausedAfterRelease), t.motion?.pausedAfterRelease === !0 ? "bad" : void 0), X(a, "hold re-asserted", s == null ? "no" : J(s), typeof s == "number" ? "bad" : void 0), X(a, "first animation", t.motion?.firstAnimationAtMs === null || t.motion?.firstAnimationAtMs === void 0 ? "not observed" : `+${J(t.motion.firstAnimationAtMs)} after t0`);
|
|
1375
1375
|
let c = t.morphs;
|
|
1376
1376
|
if (c) {
|
|
1377
|
-
let t =
|
|
1378
|
-
|
|
1377
|
+
let t = Z(e, "shared elements");
|
|
1378
|
+
X(t, "registered", Y(c.registered)), X(t, "pairable / flew", `${Y(c.pairable?.length)} · ${Y(c.flew?.length)}`);
|
|
1379
1379
|
let n = c.skipped ?? [];
|
|
1380
|
-
|
|
1380
|
+
X(t, "did not fly", n.length === 0 ? "none" : n.join(", "), n.length > 0 ? "bad" : void 0);
|
|
1381
1381
|
let r = c.duplicatedKeys ?? [];
|
|
1382
|
-
r.length > 0 &&
|
|
1382
|
+
r.length > 0 && X(t, "duplicate keys in one screen", r.join(", "), "bad"), X(t, "camera", Ft(c.camera)), X(t, "ghosts", Y(c.ghosts));
|
|
1383
1383
|
let i = (c.strandedRoles ?? 0) + (c.strandedStandIns ?? 0) + (c.strandedGhosts ?? 0) + (c.layerResidue ?? 0) + (c.leakedSheetRules ?? 0);
|
|
1384
|
-
|
|
1384
|
+
X(t, "residue at rest", i === 0 ? "clean" : `${Y(c.strandedRoles)} roles · ${Y(c.strandedStandIns)} stand-ins · ${Y(c.strandedGhosts)} ghosts · ${Y(c.layerResidue)} in layer · ${Y(c.leakedSheetRules)} rules`, i > 0 ? "bad" : void 0);
|
|
1385
1385
|
}
|
|
1386
1386
|
let l = t.tripwires ?? [];
|
|
1387
1387
|
if (l.length > 0) {
|
|
1388
|
-
let t =
|
|
1389
|
-
for (let e of l)
|
|
1388
|
+
let t = Z(e, "tripwires (one-frame events)");
|
|
1389
|
+
for (let e of l) Q(t, `+${J(e.atMs)} ${e.kind}: ${e.detail}`, "li bad");
|
|
1390
1390
|
}
|
|
1391
1391
|
let u = t.input;
|
|
1392
1392
|
if (u) {
|
|
1393
|
-
let t =
|
|
1394
|
-
|
|
1393
|
+
let t = Z(e, "what drove it");
|
|
1394
|
+
X(t, "input", `${Y(u.trusted)} trusted · ${Y(u.synthetic)} synthetic`, u.synthetic > 0 ? "bad" : void 0), X(t, "pointer types", u.pointerTypes?.join(", ") || "none observed");
|
|
1395
1395
|
}
|
|
1396
|
-
let d =
|
|
1397
|
-
|
|
1398
|
-
let g =
|
|
1399
|
-
if (_.length === 0)
|
|
1400
|
-
else for (let e of _)
|
|
1401
|
-
|
|
1396
|
+
let d = Z(e, "images"), f = t.images?.completedDuringFlight ?? 0, p = t.images?.heldDuringFlight ?? 0, m = t.images?.completedUnheld, h = typeof m == "number" ? m > 0 : f > p;
|
|
1397
|
+
X(d, "loading at t0", Y(t.images?.loadingAtStart)), X(d, "added mid-flight", Y(t.images?.addedDuringFlight)), X(d, "completed mid-flight", Y(t.images?.completedDuringFlight), h ? "bad" : void 0), X(d, "held by the engine", Y(t.images?.heldDuringFlight)), X(d, "completed without hold", Y(m), h ? "bad" : void 0), Gt(Z(e, "long tasks"), t);
|
|
1398
|
+
let g = Z(e, "landing"), _ = t.landing?.residualInlineTransforms ?? [];
|
|
1399
|
+
if (_.length === 0) X(g, "inline residue", "clean");
|
|
1400
|
+
else for (let e of _) X(g, "inline residue", q(e));
|
|
1401
|
+
X(g, "off-viewport at rest", Ft(t.landing?.offViewportAtRest));
|
|
1402
1402
|
let v = t.landing?.stuckStatuses ?? [];
|
|
1403
|
-
|
|
1403
|
+
X(g, "stuck statuses", v.length === 0 ? "none" : v.join(", "));
|
|
1404
1404
|
let y = t.landing?.orphanedHolds ?? [];
|
|
1405
|
-
if (y.length === 0)
|
|
1406
|
-
else for (let e of y)
|
|
1407
|
-
let b =
|
|
1405
|
+
if (y.length === 0) X(g, "orphaned holds", "none");
|
|
1406
|
+
else for (let e of y) X(g, "orphaned holds", q(e), "bad");
|
|
1407
|
+
let b = Z(e, "anomalies"), x = t.anomalies ?? [];
|
|
1408
1408
|
if (x.length === 0) {
|
|
1409
|
-
|
|
1409
|
+
Q(b, "none", "li dim");
|
|
1410
1410
|
return;
|
|
1411
1411
|
}
|
|
1412
|
-
for (let e of x)
|
|
1413
|
-
},
|
|
1414
|
-
|
|
1415
|
-
for (let n of t ?? [])
|
|
1416
|
-
},
|
|
1417
|
-
if (
|
|
1418
|
-
if (typeof document > "u") return { detach:
|
|
1419
|
-
let { recorder: t, ownsRecorder: n } =
|
|
1412
|
+
for (let e of x) Q(b, q(e), "li bad");
|
|
1413
|
+
}, qt = (e, t) => {
|
|
1414
|
+
Mt(e);
|
|
1415
|
+
for (let n of t ?? []) Q(e, q(n));
|
|
1416
|
+
}, Jt = 320, Yt = 2e3, Xt = 120, Zt = "Copy report JSON", Qt = () => {}, $t = null, en = (e = {}) => {
|
|
1417
|
+
if ($t) return $t;
|
|
1418
|
+
if (typeof document > "u") return { detach: Qt };
|
|
1419
|
+
let { recorder: t, ownsRecorder: n } = kt(e.recorder), { host: r, root: i } = Dt(zt), a = K("button", "toggle");
|
|
1420
1420
|
a.type = "button", a.setAttribute("data-corner", e.position ?? "bottom-right"), a.setAttribute("aria-label", "flemo devtools");
|
|
1421
|
-
let o =
|
|
1422
|
-
s.hidden = !0, a.appendChild(
|
|
1423
|
-
let c =
|
|
1421
|
+
let o = K("span", "count", "0"), s = K("span", "dot");
|
|
1422
|
+
s.hidden = !0, a.appendChild(K("span", "mark", "flemo")), a.appendChild(o), a.appendChild(s);
|
|
1423
|
+
let c = K("section", "panel");
|
|
1424
1424
|
c.hidden = !0;
|
|
1425
|
-
let l =
|
|
1425
|
+
let l = K("div", "grip");
|
|
1426
1426
|
l.setAttribute("role", "separator"), l.setAttribute("aria-label", "Resize flemo devtools panel");
|
|
1427
|
-
let u =
|
|
1427
|
+
let u = K("header", "head"), d = K("div", "env", "—"), f = K("button", "act", Zt);
|
|
1428
1428
|
f.type = "button";
|
|
1429
|
-
let p =
|
|
1429
|
+
let p = K("button", "act", "Close");
|
|
1430
1430
|
p.type = "button";
|
|
1431
|
-
let m =
|
|
1431
|
+
let m = K("button", "act", "Detach");
|
|
1432
1432
|
m.type = "button";
|
|
1433
|
-
let h =
|
|
1433
|
+
let h = K("button", "act", "A/B: off");
|
|
1434
1434
|
h.type = "button";
|
|
1435
|
-
let g =
|
|
1436
|
-
u.appendChild(d), u.appendChild(
|
|
1437
|
-
let _ =
|
|
1435
|
+
let g = K("div", "chips");
|
|
1436
|
+
u.appendChild(d), u.appendChild(K("div", "spacer")), u.appendChild(h), u.appendChild(f), u.appendChild(p), u.appendChild(m), u.appendChild(g);
|
|
1437
|
+
let _ = K("div", "body"), v = K("div", "list"), y = K("div", "detail");
|
|
1438
1438
|
_.appendChild(v), _.appendChild(y);
|
|
1439
|
-
let b =
|
|
1440
|
-
x.appendChild(
|
|
1441
|
-
let S =
|
|
1439
|
+
let b = K("div", "foot"), x = K("details");
|
|
1440
|
+
x.appendChild(K("summary", void 0, "What this cannot see"));
|
|
1441
|
+
let S = K("div");
|
|
1442
1442
|
x.appendChild(S), b.appendChild(x), c.appendChild(l), c.appendChild(u), c.appendChild(_), c.appendChild(b), i.appendChild(a), i.appendChild(c);
|
|
1443
|
-
let C = !1, w = e.initialOpen === !0, T = null, E = "", D = "", O = "", k = !1, A = 0, j = 0, M = -1, N = e.buckets && e.buckets.length > 0 ? e.buckets : ["A", "B"], P = (e) => Math.min(Math.max(e,
|
|
1443
|
+
let C = !1, w = e.initialOpen === !0, T = null, E = "", D = "", O = "", k = !1, A = 0, j = 0, M = -1, N = e.buckets && e.buckets.length > 0 ? e.buckets : ["A", "B"], P = (e) => Math.min(Math.max(e, Xt), Math.max(Xt, window.innerHeight * .9)), ee = () => {
|
|
1444
1444
|
try {
|
|
1445
|
-
let e = sessionStorage.getItem(
|
|
1445
|
+
let e = sessionStorage.getItem(Ne);
|
|
1446
1446
|
if (e === null) return null;
|
|
1447
1447
|
let t = Number.parseFloat(e);
|
|
1448
1448
|
return Number.isFinite(t) ? t : null;
|
|
@@ -1451,7 +1451,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1451
1451
|
}
|
|
1452
1452
|
}, te = (e) => {
|
|
1453
1453
|
try {
|
|
1454
|
-
sessionStorage.setItem(
|
|
1454
|
+
sessionStorage.setItem(Ne, String(Math.round(e)));
|
|
1455
1455
|
} catch {}
|
|
1456
1456
|
}, F = P(ee() ?? window.innerHeight * .4);
|
|
1457
1457
|
c.style.height = `${Math.round(F)}px`;
|
|
@@ -1465,63 +1465,63 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1465
1465
|
e !== T && (T = e, L());
|
|
1466
1466
|
}, re = () => {
|
|
1467
1467
|
let e = I(), t = e?.flights ?? [];
|
|
1468
|
-
|
|
1468
|
+
Nt(o, String(t.length));
|
|
1469
1469
|
let n = t.some((e) => (e?.anomalies?.length ?? 0) > 0);
|
|
1470
1470
|
if (s.hidden = !n, c.hidden = !w, !w) return;
|
|
1471
|
-
|
|
1471
|
+
Nt(d, It(e));
|
|
1472
1472
|
let r = JSON.stringify([
|
|
1473
1473
|
e?.overrides?.warnings ?? [],
|
|
1474
1474
|
e?.anomalies ?? [],
|
|
1475
1475
|
e?.overrides?.active ?? {}
|
|
1476
1476
|
]);
|
|
1477
|
-
r !== O && (O = r,
|
|
1478
|
-
let i =
|
|
1479
|
-
i !== E && (E = i,
|
|
1477
|
+
r !== O && (O = r, Vt(g, e)), T === null && t.length > 0 && (T = t[t.length - 1]?.id ?? null);
|
|
1478
|
+
let i = Lt(t, T);
|
|
1479
|
+
i !== E && (E = i, Ht(v, t, T, ne));
|
|
1480
1480
|
let a = t.find((e) => e?.id === T) ?? null, l = JSON.stringify(a);
|
|
1481
|
-
l !== D && (D = l,
|
|
1481
|
+
l !== D && (D = l, Kt(y, a)), k || (k = !0, qt(S, e?.blindSpots));
|
|
1482
1482
|
};
|
|
1483
1483
|
function L() {
|
|
1484
|
-
C ||
|
|
1484
|
+
C || Et() || re();
|
|
1485
1485
|
}
|
|
1486
1486
|
function ie() {
|
|
1487
1487
|
A = 0, L(), ae();
|
|
1488
1488
|
}
|
|
1489
1489
|
function ae() {
|
|
1490
|
-
A = window.setTimeout(ie, w ?
|
|
1490
|
+
A = window.setTimeout(ie, w ? Jt : Yt);
|
|
1491
1491
|
}
|
|
1492
1492
|
let oe = () => {
|
|
1493
1493
|
window.clearTimeout(A), ae();
|
|
1494
1494
|
}, se = (e) => {
|
|
1495
1495
|
w = e, oe(), L();
|
|
1496
1496
|
};
|
|
1497
|
-
a.addEventListener("click", () => se(!w)), p.addEventListener("click", () => se(!1)), m.addEventListener("click", () =>
|
|
1497
|
+
a.addEventListener("click", () => se(!w)), p.addEventListener("click", () => se(!1)), m.addEventListener("click", () => de()), h.addEventListener("click", () => {
|
|
1498
1498
|
M = M + 1 >= N.length ? -1 : M + 1;
|
|
1499
1499
|
let e = M === -1 ? null : N[M];
|
|
1500
|
-
t.mark(e),
|
|
1500
|
+
t.mark(e), Nt(h, `A/B: ${e ?? "off"}`), O = "", L();
|
|
1501
1501
|
});
|
|
1502
1502
|
let ce = () => {
|
|
1503
1503
|
if (!C) {
|
|
1504
|
-
if (
|
|
1505
|
-
window.clearTimeout(j), j = window.setTimeout(ce,
|
|
1504
|
+
if (Et()) {
|
|
1505
|
+
window.clearTimeout(j), j = window.setTimeout(ce, Jt);
|
|
1506
1506
|
return;
|
|
1507
1507
|
}
|
|
1508
|
-
|
|
1508
|
+
Nt(f, "Copied ✓"), window.clearTimeout(j), j = window.setTimeout(R, 1200);
|
|
1509
1509
|
}
|
|
1510
1510
|
};
|
|
1511
|
-
function
|
|
1512
|
-
if (
|
|
1513
|
-
j = window.setTimeout(
|
|
1511
|
+
function R() {
|
|
1512
|
+
if (Et()) {
|
|
1513
|
+
j = window.setTimeout(R, Jt);
|
|
1514
1514
|
return;
|
|
1515
1515
|
}
|
|
1516
|
-
j = 0,
|
|
1516
|
+
j = 0, Nt(f, Zt);
|
|
1517
1517
|
}
|
|
1518
|
-
let
|
|
1518
|
+
let le = (e) => {
|
|
1519
1519
|
if (C) return;
|
|
1520
|
-
if (
|
|
1521
|
-
window.clearTimeout(j), j = window.setTimeout(() =>
|
|
1520
|
+
if (Et()) {
|
|
1521
|
+
window.clearTimeout(j), j = window.setTimeout(() => le(e), Jt);
|
|
1522
1522
|
return;
|
|
1523
1523
|
}
|
|
1524
|
-
let t =
|
|
1524
|
+
let t = K("textarea");
|
|
1525
1525
|
t.value = e, t.setAttribute("aria-hidden", "true"), t.style.position = "fixed", t.style.opacity = "0", t.style.pointerEvents = "none", document.body.appendChild(t), t.select();
|
|
1526
1526
|
let n = document;
|
|
1527
1527
|
try {
|
|
@@ -1532,44 +1532,44 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1532
1532
|
f.addEventListener("click", () => {
|
|
1533
1533
|
let e = JSON.stringify(I(), null, 2), t = navigator.clipboard;
|
|
1534
1534
|
if (t && typeof t.writeText == "function") {
|
|
1535
|
-
t.writeText(e).then(ce, () =>
|
|
1535
|
+
t.writeText(e).then(ce, () => le(e));
|
|
1536
1536
|
return;
|
|
1537
1537
|
}
|
|
1538
|
-
|
|
1538
|
+
le(e);
|
|
1539
1539
|
});
|
|
1540
|
-
let
|
|
1540
|
+
let ue = (e) => {
|
|
1541
1541
|
F = P(window.innerHeight - e.clientY), c.style.height = `${Math.round(F)}px`;
|
|
1542
|
-
},
|
|
1543
|
-
window.removeEventListener("pointermove",
|
|
1542
|
+
}, z = () => {
|
|
1543
|
+
window.removeEventListener("pointermove", ue), window.removeEventListener("pointerup", z), te(F);
|
|
1544
1544
|
};
|
|
1545
1545
|
l.addEventListener("pointerdown", (e) => {
|
|
1546
|
-
e.preventDefault(), window.addEventListener("pointermove",
|
|
1546
|
+
e.preventDefault(), window.addEventListener("pointermove", ue), window.addEventListener("pointerup", z);
|
|
1547
1547
|
});
|
|
1548
|
-
function
|
|
1549
|
-
C || (C = !0, window.clearTimeout(A), A = 0, window.clearTimeout(j), j = 0, window.removeEventListener("pointermove",
|
|
1548
|
+
function de() {
|
|
1549
|
+
C || (C = !0, window.clearTimeout(A), A = 0, window.clearTimeout(j), j = 0, window.removeEventListener("pointermove", ue), window.removeEventListener("pointerup", z), r.remove(), n && t.detach(), $t = null);
|
|
1550
1550
|
}
|
|
1551
1551
|
document.body.appendChild(r), L(), ae();
|
|
1552
|
-
let fe = { detach:
|
|
1553
|
-
return
|
|
1554
|
-
},
|
|
1552
|
+
let fe = { detach: de };
|
|
1553
|
+
return $t = fe, fe;
|
|
1554
|
+
}, tn = 500, nn = 450, rn = "\n:host { all: initial; }\n.root { all: initial; }\n.hud {\n position: fixed;\n left: 50%;\n transform: translateX(-50%);\n max-width: calc(100vw - 16px);\n box-sizing: border-box;\n padding: 6px 10px;\n border-radius: 8px;\n background: #0b0f14;\n color: #e8f0f8;\n border: 1px solid #2b3a4a;\n font: 500 12px/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n white-space: pre;\n text-align: left;\n overflow-x: auto;\n -webkit-user-select: none;\n user-select: none;\n touch-action: manipulation;\n /* No transition and no keyframe anywhere in this sheet: the readout must\n never be a moving thing on a screen whose motion is under test. */\n}\n.hud[data-edge=\"top\"] { top: max(8px, env(safe-area-inset-top)); }\n.hud[data-edge=\"bottom\"] { bottom: max(8px, env(safe-area-inset-bottom)); }\n.hud[data-alarm=\"true\"] { border-color: #ff6b6b; color: #ffd9d9; }\n.hud[data-blocked=\"true\"] { border-color: #ffb020; color: #ffe9c2; }\n", an = (e) => Math.round(e * 10) / 10, on = (e) => {
|
|
1555
1555
|
if (!e) return "flemo no flight yet";
|
|
1556
1556
|
let t = e.frameSamples?.released, n = e.anomalies?.length ?? 0;
|
|
1557
|
-
return `${e.kind} ${Math.round(e.durationMs)}ms gap ${
|
|
1558
|
-
},
|
|
1557
|
+
return `${e.kind} ${Math.round(e.durationMs)}ms gap ${an(t?.maxGapMs ?? 0)} drop ${t?.over30Count ?? 0}` + (n > 0 ? ` !${n}` : " ok") + (e.bucket ? ` [${e.bucket}]` : "");
|
|
1558
|
+
}, sn = (e, t) => {
|
|
1559
1559
|
let n = [], r = (e?.preconditions ?? []).filter((e) => e.status === "violated");
|
|
1560
|
-
if (r.length > 0 && n.push(`BLOCKED ${r.map((e) => e.id).join(" ")}`), !t) return n.push(`rAF ${
|
|
1560
|
+
if (r.length > 0 && n.push(`BLOCKED ${r.map((e) => e.id).join(" ")}`), !t) return n.push(`rAF ${an(e?.environment?.rafCadence?.medianGapMs ?? 0)}ms`), n;
|
|
1561
1561
|
let i = t.frameSamples;
|
|
1562
|
-
n.push(`frames n${i?.released?.count ?? 0} med ${
|
|
1562
|
+
n.push(`frames n${i?.released?.count ?? 0} med ${an(i?.released?.medianGapMs ?? 0)} max ${an(i?.released?.maxGapMs ?? 0)}`), n.push(`motion stall ${an(t.motion?.longestStallMs ?? 0)}ms tail ${t.motion?.tailFrames ?? 0} start +${t.motion?.firstAnimationAtMs ?? "?"}ms`), n.push(`hold ${t.holds?.kind ?? "none"} rel ${t.holds?.releasedAtMs ?? "-"}ms task ${t.longTasks?.length ?? 0}`);
|
|
1563
1563
|
let a = t.morphs;
|
|
1564
1564
|
a && (a.pairable.length > 0 || a.flew.length > 0) && n.push(`morph ${a.flew.length} flew` + (a.camera ? " cam" : "") + (a.skipped.length > 0 ? ` SKIPPED ${a.skipped.length} (${a.skipped.join(",")})` : ""));
|
|
1565
1565
|
let o = t.input;
|
|
1566
1566
|
o && n.push(`input ${o.pointerTypes.join("/") || "none"}` + (o.synthetic > 0 ? ` SYNTHETIC ${o.synthetic}` : ""));
|
|
1567
1567
|
for (let e of t.anomalies ?? []) n.push(`! ${e.slice(0, 120)}`);
|
|
1568
1568
|
return n;
|
|
1569
|
-
},
|
|
1570
|
-
if (
|
|
1569
|
+
}, cn = null, ln = (e = {}) => {
|
|
1570
|
+
if (cn) return cn;
|
|
1571
1571
|
if (typeof document > "u") return { detach: () => {} };
|
|
1572
|
-
let { recorder: t, ownsRecorder: n } =
|
|
1572
|
+
let { recorder: t, ownsRecorder: n } = kt(e.recorder), r = e.buckets && e.buckets.length > 0 ? e.buckets : ["A", "B"], { host: i, root: a } = Dt(rn), o = document.createElement("div");
|
|
1573
1573
|
o.className = "hud", o.setAttribute("data-edge", e.position ?? "top"), o.setAttribute("role", "status"), o.textContent = "flemo attaching", a.appendChild(o);
|
|
1574
1574
|
let s = !1, c = e.initialExpanded === !0, l = -1, u = 0, d = 0, f = !1, p = "", m = () => {
|
|
1575
1575
|
try {
|
|
@@ -1578,29 +1578,86 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1578
1578
|
return null;
|
|
1579
1579
|
}
|
|
1580
1580
|
}, h = () => {
|
|
1581
|
-
if (s ||
|
|
1582
|
-
let e = m(), t = e?.flights ?? [], n = t[t.length - 1], r = [
|
|
1583
|
-
c && r.push(...
|
|
1581
|
+
if (s || Et()) return;
|
|
1582
|
+
let e = m(), t = e?.flights ?? [], n = t[t.length - 1], r = [on(n)];
|
|
1583
|
+
c && r.push(...sn(e, n));
|
|
1584
1584
|
let i = r.join("\n"), a = (e?.preconditions ?? []).some((e) => e.status === "violated"), l = (n?.anomalies?.length ?? 0) > 0;
|
|
1585
1585
|
i !== p && (p = i, o.textContent = i), o.setAttribute("data-alarm", l ? "true" : "false"), o.setAttribute("data-blocked", a ? "true" : "false");
|
|
1586
1586
|
}, g = () => {
|
|
1587
|
-
u = 0, h(), u = window.setTimeout(g,
|
|
1587
|
+
u = 0, h(), u = window.setTimeout(g, tn);
|
|
1588
1588
|
}, _ = () => {
|
|
1589
1589
|
l = l + 1 >= r.length ? -1 : l + 1, t.mark(l === -1 ? null : r[l]), p = "", h();
|
|
1590
1590
|
};
|
|
1591
1591
|
o.addEventListener("pointerdown", () => {
|
|
1592
1592
|
f = !1, window.clearTimeout(d), d = window.setTimeout(() => {
|
|
1593
1593
|
f = !0, _();
|
|
1594
|
-
},
|
|
1594
|
+
}, nn);
|
|
1595
1595
|
}), o.addEventListener("pointerup", () => {
|
|
1596
1596
|
window.clearTimeout(d), d = 0, !f && (c = !c, p = "", h());
|
|
1597
1597
|
}), o.addEventListener("pointercancel", () => window.clearTimeout(d));
|
|
1598
1598
|
let v = () => {
|
|
1599
|
-
s || (s = !0, window.clearTimeout(u), u = 0, window.clearTimeout(d), d = 0, i.remove(), n && t.detach(),
|
|
1599
|
+
s || (s = !0, window.clearTimeout(u), u = 0, window.clearTimeout(d), d = 0, i.remove(), n && t.detach(), cn = null);
|
|
1600
1600
|
};
|
|
1601
|
-
document.body.appendChild(i), h(), u = window.setTimeout(g,
|
|
1601
|
+
document.body.appendChild(i), h(), u = window.setTimeout(g, tn);
|
|
1602
1602
|
let y = { detach: v };
|
|
1603
|
-
return
|
|
1603
|
+
return cn = y, y;
|
|
1604
|
+
}, un = 1200, dn = 2, fn = () => [...document.querySelectorAll(`[${d}]`)], pn = (e) => H(getComputedStyle(e).transform) ?? 0, mn = (e) => {
|
|
1605
|
+
let t = [];
|
|
1606
|
+
for (let n of e) {
|
|
1607
|
+
let e = n;
|
|
1608
|
+
if (typeof e.getAnimations == "function") for (let n of e.getAnimations()) {
|
|
1609
|
+
let e = n, r = n.currentTime, i = typeof r == "number" ? Math.round(r) : 0;
|
|
1610
|
+
t.push(`${e.animationName ?? "waapi"}|${n.playState}|ct=${i}|rate=${n.playbackRate}`);
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
return t;
|
|
1614
|
+
}, hn = (e) => e.length === 0 ? 0 : e.reduce((e, t) => e + t, 0) / e.length, $ = (e) => Math.round(e * 100) / 100, gn = (e) => {
|
|
1615
|
+
/* v8 ignore next -- SSR guard: there is nothing to watch without a document. */
|
|
1616
|
+
if (typeof document > "u") return { detach: () => {} };
|
|
1617
|
+
let t = e.now ?? (() => performance.now()), n = e.schedule ?? ((e) => {
|
|
1618
|
+
requestAnimationFrame(e);
|
|
1619
|
+
}), r = () => {
|
|
1620
|
+
let r = fn();
|
|
1621
|
+
if (r.length === 0) return;
|
|
1622
|
+
let i = Math.max(...r.map((e) => Math.abs(pn(e))));
|
|
1623
|
+
if (i < dn) return;
|
|
1624
|
+
let a = t(), o = [], s = () => {
|
|
1625
|
+
let r = fn();
|
|
1626
|
+
if (o.push({
|
|
1627
|
+
t: Math.round(t() - a),
|
|
1628
|
+
x: r.map((e) => $(pn(e))),
|
|
1629
|
+
animations: mn(r)
|
|
1630
|
+
}), t() - a < 1200) {
|
|
1631
|
+
n(s);
|
|
1632
|
+
return;
|
|
1633
|
+
}
|
|
1634
|
+
let c = o[0].x, l = 0;
|
|
1635
|
+
for (let [e, t] of c.entries()) Math.abs(t) > Math.abs(c[l]) && (l = e);
|
|
1636
|
+
let u = o.map((e) => e.x[l] ?? 0), d = [];
|
|
1637
|
+
for (let e = 1; e < u.length; e += 1) {
|
|
1638
|
+
let t = Math.abs(u[e] - u[e - 1]);
|
|
1639
|
+
t > 0 && d.push(t);
|
|
1640
|
+
}
|
|
1641
|
+
let f = hn(d.slice(0, 3)), p = hn(d.slice(-3));
|
|
1642
|
+
e.onRelease({
|
|
1643
|
+
samples: o,
|
|
1644
|
+
travelAtReleasePx: $(i),
|
|
1645
|
+
biggestStepPx: $(Math.max(0, ...d)),
|
|
1646
|
+
openingStepPx: $(f),
|
|
1647
|
+
closingStepPx: $(p),
|
|
1648
|
+
eased: d.length > 3 && p < f * .5,
|
|
1649
|
+
teleported: Math.max(0, ...d) > i * .5
|
|
1650
|
+
});
|
|
1651
|
+
};
|
|
1652
|
+
n(s);
|
|
1653
|
+
}, i = ["pointerup", "pointercancel"];
|
|
1654
|
+
for (let e of i) document.addEventListener(e, r, {
|
|
1655
|
+
capture: !0,
|
|
1656
|
+
passive: !0
|
|
1657
|
+
});
|
|
1658
|
+
return { detach: () => {
|
|
1659
|
+
for (let e of i) document.removeEventListener(e, r, { capture: !0 });
|
|
1660
|
+
} };
|
|
1604
1661
|
};
|
|
1605
1662
|
//#endregion
|
|
1606
|
-
export { c as BLIND_SPOTS, Fe as CORE_FLAGS, Pe as DEVTOOLS_OWNED_FLAGS,
|
|
1663
|
+
export { c as BLIND_SPOTS, Fe as CORE_FLAGS, Pe as DEVTOOLS_OWNED_FLAGS, Ie as FLAG_REGISTRY, ge as JUDGING_PROTOCOL, e as LONG_GAP_MS, i as MID_FLIGHT_TASK_MS, n as OPENING_WINDOW_LEAD_MS, r as OPENING_WINDOW_TAIL_MS, Ne as PANEL_HEIGHT_KEY, ht as REPORT_SCHEMA_VERSION, W as RETIRED_FLAGS, Le as RETIRED_MARKER, a as STALL_MS, t as STUCK_STATUS_MS, un as SWIPE_PROBE_MS, We as TRACE_KEY, ln as attachDevtoolsHud, en as attachDevtoolsPanel, wt as attachFlightRecorder, gn as attachSwipeProbe, ne as captureEnvironment, ve as classifyDriver, qe as clearTrace, _e as computeFrameStats, V as computePhaseStats, o as deriveFlightAnomalies, Ue as deriveOverrideWarnings, at as derivePreconditions, s as deriveReportAnomalies, mt as deriveVerdict, N as detectEngine, F as developmentHints, P as isEmulationSuspected, ye as kindFromStatus, Je as loadTrace, H as parseTranslateX, ee as sampleRafCadence, Ke as saveTrace, He as snapshotOverrides, u as summariseBuckets };
|