@flemo/devtools 0.2.2 → 0.4.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/README.md +77 -302
- package/dist/__tests__/domProtocol.test.d.ts +1 -0
- package/dist/anomalies.d.ts +0 -4
- package/dist/domProtocol.d.ts +22 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.mjs +386 -380
- package/dist/noop.d.ts +1 -1
- package/dist/noop.mjs +122 -103
- package/dist/overrides.d.ts +44 -7
- package/dist/types.d.ts +0 -14
- package/package.json +7 -6
package/dist/index.mjs
CHANGED
|
@@ -11,7 +11,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
11
11
|
return d.holdReassertedAtMs !== null && n.push(`hold re-asserted ${d.holdReassertedAtMs}ms into the flight, after it had already released (an interleaved commit wrote the stale paused hold attribute over a running flight — the flemo 2026-08-18 release-race signature; the motion pauses while every timing metric stays clean)`), d.pausedAfterRelease && n.push("compiled animation reported playState=paused after its release (the flight was posed and then stopped mid-motion, not merely starved of frames)"), d.longestStallMs >= 48 && n.push(`motion stalled ${d.longestStallMs}ms mid-flight (${d.stalledFrames}/${d.sampledFrames} released frames advanced neither the animation clock nor the pose — freeze, or freeze-then-leap if the flight still landed on time)`), d.sampledFrames === 0 && e.releasedAtMs !== null && n.push("no released frames were sampled (the flight ended at or before its own hold release — the visible motion, if any, was never observed)"), f.completedUnheld > 0 && n.push(`${f.completedUnheld} image(s) finished loading mid-flight without a hold (${f.completedDuringFlight} completed, ${f.heldDuringFlight} held; ${f.loadingAtStart} were loading at t0, ${f.addedDuringFlight} arrived mid-flight) — each decode rasters on the moving layer and costs a present; this is the warm-side image-hold regression`), l.orphanedHolds.length > 0 && n.push(`hold markers left on the page at rest: ${l.orphanedHolds.join("; ")} (whatever they hide has no owner left to reveal it — the permanently-blank-avatar class)`), l.residualInlineTransforms.length > 0 && n.push(`residual inline style after COMPLETED: ${l.residualInlineTransforms.join("; ")} (landing cleanup failure — the landed scope belongs to the compiled rest rules)`), l.offViewportAtRest && n.push("screen resting at from-pose while COMPLETED+active (blank-viewport signature — the flemo PR #259 class: a residual pose left the landed screen parked off-viewport)"), l.stuckStatuses.length > 0 && n.push(`transitional status stuck >${t / 1e3}s: ${l.stuckStatuses.join(", ")} (navigation queue lock or missed animationend — later navigations will be swallowed)`), i === "unknown" && n.push("driver could not be classified (no running flemo-* CSSAnimation and no player inline-style signature observed — zero-duration flight, or the sampler attached after motion ended)"), n;
|
|
12
12
|
}, o = (e) => {
|
|
13
13
|
let n = [];
|
|
14
|
-
if (e.
|
|
14
|
+
if (e.emulationSuspected) {
|
|
15
15
|
let t = /Win/i.test(e.platform) ? " (Windows touch hardware makes this signal ambiguous — confirm the DevTools device toolbar state)" : "";
|
|
16
16
|
n.push("DevTools device emulation suspected — the page composites to a rescaled surface, so visual reports from this session are untrustworthy; judge motion in a plain window or on a real device" + t);
|
|
17
17
|
}
|
|
@@ -21,24 +21,33 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
21
21
|
"Display-hardware effects: local dimming, backlight modulation, and panel overdrive alter perceived motion and are invisible to every web API.",
|
|
22
22
|
"Compositor-internal present skips: a frame can be produced on time (clean rAF, clean player gaps) yet dropped or delayed inside the compositor's present queue; only platform tools (about:tracing, Instruments) see that layer.",
|
|
23
23
|
"DevTools device emulation composites the page to a rescaled surface: every in-page instrument reads the pre-scale surface and reports clean while the eye watches the post-scale one, so emulated sessions grow shimmer/flash artifacts that do not exist in a plain window or on a real device."
|
|
24
|
-
], c =
|
|
24
|
+
], c = "data-flemo-screen", l = "data-flemo-status", u = "data-flemo-active", d = "data-flemo-anim-hold", f = "data-flemo-img-hold", p = "data-flemo-held-arrival", m = "data-flemo-part-name", h = "data-flemo-decorator", g = "data-flemo-bar", _ = "data-flemo-devtools-panel", v = [
|
|
25
|
+
"PUSHING",
|
|
26
|
+
"POPPING",
|
|
27
|
+
"REPLACING"
|
|
28
|
+
], y = [
|
|
29
|
+
"true",
|
|
30
|
+
"park",
|
|
31
|
+
"park-under",
|
|
32
|
+
"park-over"
|
|
33
|
+
], b = (e) => `[${e}]`, ee = (e, t) => `[${e}="${t}"]`, x = () => {
|
|
25
34
|
if (typeof navigator > "u") return null;
|
|
26
35
|
let e = navigator.userAgentData;
|
|
27
36
|
return !e || !Array.isArray(e.brands) ? null : e.brands.map((e) => ({
|
|
28
37
|
brand: String(e.brand ?? ""),
|
|
29
38
|
version: String(e.version ?? "")
|
|
30
39
|
}));
|
|
31
|
-
},
|
|
40
|
+
}, S = () => {
|
|
32
41
|
if (typeof navigator > "u") return "unknown";
|
|
33
|
-
let e =
|
|
42
|
+
let e = x();
|
|
34
43
|
if (e?.some((e) => /Chromium/i.test(e.brand))) return "blink";
|
|
35
44
|
let t = navigator.userAgent ?? "";
|
|
36
45
|
return /Firefox|FxiOS/i.test(t) ? "gecko" : e || /AppleWebKit/i.test(t) && !/Chrome|Chromium|Android/i.test(t) ? "webkit" : /Android/i.test(t) ? "blink" : "unknown";
|
|
37
|
-
},
|
|
38
|
-
if (typeof navigator > "u" ||
|
|
46
|
+
}, C = () => {
|
|
47
|
+
if (typeof navigator > "u" || S() !== "blink") return !1;
|
|
39
48
|
let e = navigator.platform ?? "";
|
|
40
49
|
return /Mac|Win|Linux/i.test(e) ? /Android/i.test(navigator.userAgent ?? "") && !/Mac|Win/i.test(e) ? /Linux (x86_64|i686)/i.test(e) : (navigator.maxTouchPoints ?? 0) > 0 : !1;
|
|
41
|
-
},
|
|
50
|
+
}, te = (e = 20) => new Promise((t) => {
|
|
42
51
|
let n = Number.isFinite(e) ? Math.max(1, Math.floor(e)) : 20;
|
|
43
52
|
if (typeof requestAnimationFrame != "function" || typeof performance > "u") {
|
|
44
53
|
t({
|
|
@@ -60,13 +69,13 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
60
69
|
requestAnimationFrame(a);
|
|
61
70
|
};
|
|
62
71
|
requestAnimationFrame(a);
|
|
63
|
-
}),
|
|
72
|
+
}), w = () => {
|
|
64
73
|
try {
|
|
65
74
|
return typeof PerformanceObserver < "u" && Array.isArray(PerformanceObserver.supportedEntryTypes) && PerformanceObserver.supportedEntryTypes.includes("longtask");
|
|
66
75
|
} catch {
|
|
67
76
|
return !1;
|
|
68
77
|
}
|
|
69
|
-
},
|
|
78
|
+
}, T = (e) => {
|
|
70
79
|
let t = typeof navigator < "u" ? navigator : null, n = typeof window < "u" ? window : null, r = !1;
|
|
71
80
|
try {
|
|
72
81
|
r = n?.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? !1;
|
|
@@ -75,8 +84,8 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
75
84
|
}
|
|
76
85
|
return {
|
|
77
86
|
userAgent: t?.userAgent ?? "",
|
|
78
|
-
uaBrands:
|
|
79
|
-
engine:
|
|
87
|
+
uaBrands: x(),
|
|
88
|
+
engine: S(),
|
|
80
89
|
platform: t?.platform ?? "",
|
|
81
90
|
maxTouchPoints: t?.maxTouchPoints ?? 0,
|
|
82
91
|
devicePixelRatio: n?.devicePixelRatio ?? 1,
|
|
@@ -91,169 +100,192 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
91
100
|
visualViewportScale: n?.visualViewport?.scale ?? null,
|
|
92
101
|
rafCadence: e,
|
|
93
102
|
reducedMotion: r,
|
|
94
|
-
emulationSuspected:
|
|
103
|
+
emulationSuspected: C(),
|
|
95
104
|
observation: {
|
|
96
|
-
longTasks:
|
|
105
|
+
longTasks: w(),
|
|
97
106
|
elementAnimations: typeof Element < "u" && typeof Element.prototype.getAnimations == "function",
|
|
98
107
|
playerGapMirror: Array.isArray(n?.__flemoPlayerGaps)
|
|
99
108
|
}
|
|
100
109
|
};
|
|
101
|
-
},
|
|
110
|
+
}, E = [
|
|
102
111
|
"DevTools must be CLOSED while judging motion. An open inspector serializes requests and repaints its own panels on the same machine; the 2026-08 campaign's entire residual 'stutter' was this, and it is invisible to every in-page metric.",
|
|
103
112
|
"No screen recording or display capture while judging. A capture client forces WindowServer to composite every vsync, which SUPPRESSES the symptom — a capture that looks smooth proves nothing about the uncaptured session.",
|
|
104
113
|
"Judge with real input (a finger, a mouse). Synthetic dispatch — evaluate().click() and friends — never fires pointerdown, so it bypasses the swipe/gesture machinery that a real navigation goes through.",
|
|
105
114
|
"Establish the viewing configuration before believing any verdict: device emulation off, which physical display, its refresh rate and HiDPI scaling, Low Power Mode. Ask for a photo of the setup if it is not certain."
|
|
106
|
-
],
|
|
115
|
+
], D = "flemo:devtools-panel-height", O = [{
|
|
116
|
+
key: "flemo:devtools",
|
|
117
|
+
storage: "session",
|
|
118
|
+
kind: "opt-in-diagnostic",
|
|
119
|
+
values: "\"on\" / \"off\"",
|
|
120
|
+
fallback: "off",
|
|
121
|
+
effect: "arms this flight recorder in the playground (?devtools=on)"
|
|
122
|
+
}, {
|
|
123
|
+
key: D,
|
|
124
|
+
storage: "session",
|
|
125
|
+
kind: "production-state",
|
|
126
|
+
values: "a pixel height",
|
|
127
|
+
fallback: "(the panel's default height)",
|
|
128
|
+
effect: "the drawer height this panel was last dragged to"
|
|
129
|
+
}], k = [], A = [...k, ...O], j = [
|
|
107
130
|
{
|
|
108
|
-
key: "flemo:
|
|
109
|
-
storage: "
|
|
110
|
-
|
|
111
|
-
description: "learned driver ledger ('css' = player demoted on this device, 'raf' = clean probe)"
|
|
131
|
+
key: "flemo:sixty",
|
|
132
|
+
storage: "session",
|
|
133
|
+
retiredWith: "the steady-60 verdict seed, now document-scoped module state (2026-08-31)"
|
|
112
134
|
},
|
|
113
135
|
{
|
|
114
|
-
key: "flemo:
|
|
136
|
+
key: "flemo:settle-gate",
|
|
115
137
|
storage: "session",
|
|
116
|
-
|
|
117
|
-
description: "hard driver pin ('css@<epoch-ms>' / 'raf@<epoch-ms>', 24h TTL) — pins EVERY transition"
|
|
138
|
+
retiredWith: "the engine diagnostic surface (2026-08-31)"
|
|
118
139
|
},
|
|
119
140
|
{
|
|
120
|
-
key: "flemo:
|
|
141
|
+
key: "flemo:arrivalhold",
|
|
121
142
|
storage: "session",
|
|
122
|
-
|
|
123
|
-
description: "steady-60 display verdict seed ('high' latches, a count seeds the streak)"
|
|
143
|
+
retiredWith: "the engine diagnostic surface (2026-08-31)"
|
|
124
144
|
},
|
|
125
145
|
{
|
|
126
|
-
key: "flemo:
|
|
146
|
+
key: "flemo:deskflip",
|
|
127
147
|
storage: "session",
|
|
128
|
-
|
|
129
|
-
description: "LPM release-latency seed (learned)"
|
|
148
|
+
retiredWith: "the engine diagnostic surface (2026-08-31)"
|
|
130
149
|
},
|
|
131
150
|
{
|
|
132
|
-
key: "flemo:
|
|
151
|
+
key: "flemo:deskhead",
|
|
133
152
|
storage: "session",
|
|
134
|
-
|
|
135
|
-
description: "Blink landing pixel-snap easing A/B"
|
|
153
|
+
retiredWith: "the engine diagnostic surface (2026-08-31)"
|
|
136
154
|
},
|
|
137
155
|
{
|
|
138
|
-
key: "flemo:
|
|
156
|
+
key: "flemo:creep",
|
|
139
157
|
storage: "session",
|
|
140
|
-
|
|
141
|
-
description: "flight-scoped <img> reveal hold"
|
|
158
|
+
retiredWith: "the engine diagnostic surface (2026-08-31)"
|
|
142
159
|
},
|
|
143
160
|
{
|
|
144
|
-
key: "flemo:
|
|
161
|
+
key: "flemo:relcommit",
|
|
145
162
|
storage: "session",
|
|
146
|
-
|
|
147
|
-
description: "render-settle entry gate override"
|
|
163
|
+
retiredWith: "the engine diagnostic surface (2026-08-31)"
|
|
148
164
|
},
|
|
149
165
|
{
|
|
150
|
-
key: "flemo:
|
|
166
|
+
key: "flemo:imgoffload",
|
|
151
167
|
storage: "session",
|
|
152
|
-
|
|
153
|
-
description: "anchored-opening handoff (POP-scoped)"
|
|
168
|
+
retiredWith: "the engine diagnostic surface (2026-08-31)"
|
|
154
169
|
},
|
|
155
170
|
{
|
|
156
|
-
key: "flemo:
|
|
171
|
+
key: "flemo:governed",
|
|
157
172
|
storage: "session",
|
|
158
|
-
|
|
159
|
-
description: "handoff point override (ms)"
|
|
173
|
+
retiredWith: "the engine diagnostic surface (2026-08-31)"
|
|
160
174
|
},
|
|
161
175
|
{
|
|
162
|
-
key: "flemo:
|
|
176
|
+
key: "flemo:imghold",
|
|
163
177
|
storage: "session",
|
|
164
|
-
|
|
165
|
-
description: "force the scrub-WAAPI value-application tier"
|
|
178
|
+
retiredWith: "the image reveal hold, whose only arming path it was (2026-08-31)"
|
|
166
179
|
},
|
|
167
180
|
{
|
|
168
|
-
key: "flemo:
|
|
181
|
+
key: "flemo:preraster",
|
|
169
182
|
storage: "session",
|
|
170
|
-
|
|
171
|
-
description: "player device-pixel snap policy override"
|
|
183
|
+
retiredWith: "the REST-time scope promotion, whose only arming path it was (2026-08-31)"
|
|
172
184
|
},
|
|
173
185
|
{
|
|
174
|
-
key: "flemo:
|
|
186
|
+
key: "flemo:parkhead",
|
|
175
187
|
storage: "session",
|
|
176
|
-
|
|
177
|
-
description: "'hybrid' snap jitter-band width (device px)"
|
|
188
|
+
retiredWith: "the engine diagnostic surface — the park head is unconditional (2026-08-31)"
|
|
178
189
|
},
|
|
179
190
|
{
|
|
180
191
|
key: "flemo:layers",
|
|
181
192
|
storage: "session",
|
|
182
|
-
|
|
183
|
-
|
|
193
|
+
retiredWith: "the resident-layer experiment (2026-08-31)"
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
key: "flemo:morph",
|
|
197
|
+
storage: "session",
|
|
198
|
+
retiredWith: "the morph decision trace (2026-08-31)"
|
|
184
199
|
},
|
|
185
200
|
{
|
|
186
201
|
key: "flemo:freeze",
|
|
187
202
|
storage: "session",
|
|
188
|
-
|
|
189
|
-
description: "keep the direct prev screen live"
|
|
203
|
+
retiredWith: "the shallow-freeze experiment (2026-08-31)"
|
|
190
204
|
},
|
|
191
205
|
{
|
|
192
|
-
key: "flemo:
|
|
206
|
+
key: "flemo:motion-driver",
|
|
207
|
+
storage: "local",
|
|
208
|
+
retiredWith: "the per-origin driver demotion ledger (2026-08-19)"
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
key: "flemo:motion-driver-force",
|
|
193
212
|
storage: "session",
|
|
194
|
-
|
|
195
|
-
description: "promote the entering content layer through the hold"
|
|
213
|
+
retiredWith: "the hard driver pin, with the rAF player (2026-08-22)"
|
|
196
214
|
},
|
|
197
215
|
{
|
|
198
|
-
key: "flemo:
|
|
216
|
+
key: "flemo:landing-snap",
|
|
199
217
|
storage: "session",
|
|
200
|
-
|
|
201
|
-
description: "image decode offloader override"
|
|
218
|
+
retiredWith: "the integer-device-pixel landing snap, falsified on device (2026-08-22)"
|
|
202
219
|
},
|
|
203
220
|
{
|
|
204
|
-
key: "flemo:
|
|
221
|
+
key: "flemo:handoff",
|
|
222
|
+
storage: "session",
|
|
223
|
+
retiredWith: "the player's anchored-opening handoff (2026-08-22)"
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
key: "flemo:handoffms",
|
|
205
227
|
storage: "session",
|
|
206
|
-
|
|
207
|
-
|
|
228
|
+
retiredWith: "the player's anchored-opening handoff (2026-08-22)"
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
key: "flemo:apply",
|
|
232
|
+
storage: "session",
|
|
233
|
+
retiredWith: "the scrub-WAAPI value-application tier (2026-08-22)"
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
key: "flemo:snap",
|
|
237
|
+
storage: "session",
|
|
238
|
+
retiredWith: "the player's device-pixel snap policy (2026-08-22)"
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
key: "flemo:snapband",
|
|
242
|
+
storage: "session",
|
|
243
|
+
retiredWith: "the player's device-pixel snap policy (2026-08-22)"
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
key: "flemo:lat",
|
|
247
|
+
storage: "session",
|
|
248
|
+
retiredWith: "the Low Power Mode release-latency probe (2026-08-22)"
|
|
208
249
|
}
|
|
209
|
-
],
|
|
250
|
+
], M = "(retired — the library no longer reads this)", N = (e) => {
|
|
210
251
|
try {
|
|
211
252
|
let t = e === "session" ? sessionStorage : localStorage;
|
|
212
253
|
return t.length, t;
|
|
213
254
|
} catch {
|
|
214
255
|
return null;
|
|
215
256
|
}
|
|
216
|
-
},
|
|
257
|
+
}, P = (e, t) => {
|
|
217
258
|
try {
|
|
218
259
|
return e ? e.getItem(t) : null;
|
|
219
260
|
} catch {
|
|
220
261
|
return null;
|
|
221
262
|
}
|
|
222
|
-
},
|
|
223
|
-
let e = {}, t =
|
|
224
|
-
for (let r of
|
|
225
|
-
let i =
|
|
263
|
+
}, ne = new Set(A.map((e) => e.key)), re = new Set(j.map((e) => e.key)), F = () => {
|
|
264
|
+
let e = {}, t = N("session"), n = N("local");
|
|
265
|
+
for (let r of A) {
|
|
266
|
+
let i = P(r.storage === "session" ? t : n, r.key);
|
|
226
267
|
i !== null && (e[r.key] = i);
|
|
227
268
|
}
|
|
228
|
-
let r
|
|
229
|
-
|
|
269
|
+
for (let r of j) for (let [i, a] of [[t, "sessionStorage"], [n, "localStorage"]]) {
|
|
270
|
+
let t = P(i, r.key);
|
|
271
|
+
t !== null && (e[`${r.key} (${a}) ${M}`] = t);
|
|
272
|
+
}
|
|
230
273
|
for (let [r, i] of [[t, "sessionStorage"], [n, "localStorage"]]) if (r) try {
|
|
231
274
|
for (let t = 0; t < r.length; t += 1) {
|
|
232
275
|
let n = r.key(t);
|
|
233
|
-
!n || !n.startsWith("flemo:") ||
|
|
276
|
+
!n || !n.startsWith("flemo:") || ne.has(n) || re.has(n) || (e[`${n} (${i}, unknown key)`] = r.getItem(n) ?? "");
|
|
234
277
|
}
|
|
235
278
|
} catch {}
|
|
236
279
|
return e;
|
|
237
|
-
},
|
|
280
|
+
}, I = (e) => {
|
|
238
281
|
let t = [];
|
|
239
|
-
for (let [n, r] of Object.entries(e)) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
}
|
|
244
|
-
if (n === _) {
|
|
245
|
-
t.push(`${n}=${r} — legacy localStorage driver pin present. The library removes it on sight and never honors it, but its existence means an old A/B session left residue on this profile.`);
|
|
246
|
-
continue;
|
|
247
|
-
}
|
|
248
|
-
if (n.startsWith(`${g} `)) {
|
|
249
|
-
t.push(`${n}=${r} — a driver force pin was observed this session (see marker in the key). Even a since-cleared pin may have shaped early driver decisions; treat this session's routing as suspect.`);
|
|
250
|
-
continue;
|
|
251
|
-
}
|
|
252
|
-
let e = h.find((e) => n === e.key || n.startsWith(`${e.key} `));
|
|
253
|
-
!e || e.key === "flemo:devtools" || (e.kind === "opt-in-diagnostic" ? t.push(`${n}=${r} — opt-in diagnostic active (${e.description}); behavior differs from stock. Possible left-over A/B toggle from an earlier debugging session.`) : e.kind === "production-default-with-override" && t.push(`${n}=${r} — production default overridden for this session (${e.description}).`));
|
|
282
|
+
for (let [n, r] of Object.entries(e)) if (n.includes("(retired — the library no longer reads this)")) {
|
|
283
|
+
let e = n.slice(0, n.indexOf(" (")), i = j.find((t) => t.key === e);
|
|
284
|
+
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.`);
|
|
285
|
+
continue;
|
|
254
286
|
}
|
|
255
287
|
return t;
|
|
256
|
-
},
|
|
288
|
+
}, L = (e) => Math.round(e * 10) / 10, R = (e) => {
|
|
257
289
|
if (e.length === 0) return {
|
|
258
290
|
count: 0,
|
|
259
291
|
medianGapMs: 0,
|
|
@@ -263,11 +295,11 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
263
295
|
let t = [...e].sort((e, t) => e - t);
|
|
264
296
|
return {
|
|
265
297
|
count: e.length,
|
|
266
|
-
medianGapMs:
|
|
267
|
-
maxGapMs:
|
|
298
|
+
medianGapMs: L(t[Math.floor(t.length / 2)]),
|
|
299
|
+
maxGapMs: L(t[t.length - 1]),
|
|
268
300
|
over30Count: e.filter((e) => e >= 30).length
|
|
269
301
|
};
|
|
270
|
-
},
|
|
302
|
+
}, ie = (e, t = []) => {
|
|
271
303
|
let n = [...e, ...t];
|
|
272
304
|
return {
|
|
273
305
|
...n.length === 0 ? {
|
|
@@ -278,21 +310,21 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
278
310
|
let e = [...n].sort((e, t) => e - t);
|
|
279
311
|
return {
|
|
280
312
|
count: n.length,
|
|
281
|
-
medianGapMs:
|
|
282
|
-
maxGapMs:
|
|
313
|
+
medianGapMs: L(e[Math.floor(e.length / 2)]),
|
|
314
|
+
maxGapMs: L(e[e.length - 1])
|
|
283
315
|
};
|
|
284
316
|
})(),
|
|
285
|
-
longGaps: n.filter((e) => e >= 30).map(
|
|
286
|
-
held:
|
|
287
|
-
released:
|
|
317
|
+
longGaps: n.filter((e) => e >= 30).map(L),
|
|
318
|
+
held: R(e),
|
|
319
|
+
released: R(t)
|
|
288
320
|
};
|
|
289
|
-
},
|
|
290
|
-
maxMs:
|
|
321
|
+
}, z = (e) => e.length === 0 ? null : {
|
|
322
|
+
maxMs: L(Math.max(...e)),
|
|
291
323
|
over30Count: e.filter((e) => e >= 30).length
|
|
292
|
-
},
|
|
324
|
+
}, ae = (e) => {
|
|
293
325
|
let t = e.playerSuppression || e.playerAdvance;
|
|
294
326
|
return t && e.compiledAnimation ? "mixed" : t ? "player" : e.compiledAnimation ? "compiled" : "unknown";
|
|
295
|
-
},
|
|
327
|
+
}, oe = (e) => e === "PUSHING" ? "PUSH" : e === "POPPING" ? "POP" : e === "REPLACING" ? "REPLACE" : null, se = (e) => {
|
|
296
328
|
let t = /^matrix3d\(([^)]+)\)$/.exec(e.trim());
|
|
297
329
|
if (t) {
|
|
298
330
|
let e = t[1].split(",").map((e) => Number(e.trim()));
|
|
@@ -304,23 +336,14 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
304
336
|
return e.length === 6 && Number.isFinite(e[4]) ? e[4] : null;
|
|
305
337
|
}
|
|
306
338
|
return null;
|
|
307
|
-
},
|
|
308
|
-
|
|
309
|
-
"POPPING",
|
|
310
|
-
"REPLACING"
|
|
311
|
-
]), j = /* @__PURE__ */ new Set([
|
|
312
|
-
"true",
|
|
313
|
-
"park",
|
|
314
|
-
"park-under",
|
|
315
|
-
"park-over"
|
|
316
|
-
]), M = "[data-flemo-screen]", N = "data-flemo-status", te = "data-flemo-active", P = "data-flemo-anim-hold", F = 2, I = 2e3, L = "data-flemo-img-hold", ne = "data-flemo-held-arrival", re = 2, R = 200, ie = 1e3, z = (e) => Math.round(e * 10) / 10, B = null, V = () => window, ae = (e = {}) => {
|
|
317
|
-
if (B) return B;
|
|
339
|
+
}, ce = "2", B = new Set(v), V = new Set(y), le = b(c), H = d, ue = 2, de = 2e3, fe = 2, pe = 200, me = 1e3, U = (e) => Math.round(e * 10) / 10, he = null, ge = () => window, _e = (e = {}) => {
|
|
340
|
+
if (he) return he;
|
|
318
341
|
if (typeof window > "u" || typeof document > "u") return {
|
|
319
342
|
detach: () => {},
|
|
320
343
|
report: () => ({
|
|
321
344
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
322
345
|
version: "2",
|
|
323
|
-
environment:
|
|
346
|
+
environment: T({
|
|
324
347
|
medianGapMs: null,
|
|
325
348
|
sampleCount: 0
|
|
326
349
|
}),
|
|
@@ -328,51 +351,47 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
328
351
|
active: {},
|
|
329
352
|
warnings: ["no DOM available — recorder ran inert"]
|
|
330
353
|
},
|
|
331
|
-
driverPolicy: {
|
|
332
|
-
demotion: null,
|
|
333
|
-
forcePin: null
|
|
334
|
-
},
|
|
335
354
|
flights: [],
|
|
336
355
|
anomalies: [],
|
|
337
356
|
blindSpots: [...s],
|
|
338
|
-
judgingProtocol: [...
|
|
357
|
+
judgingProtocol: [...E]
|
|
339
358
|
})
|
|
340
359
|
};
|
|
341
|
-
let n = e.maxFlights ?? 50, r = e.log ?? !1, i = e.installGlobal ?? !0, c =
|
|
360
|
+
let n = e.maxFlights ?? 50, r = e.log ?? !1, i = e.installGlobal ?? !0, c = F(), d = {
|
|
342
361
|
medianGapMs: null,
|
|
343
362
|
sampleCount: 0
|
|
344
363
|
};
|
|
345
|
-
|
|
346
|
-
|
|
364
|
+
te().then((e) => {
|
|
365
|
+
d = e;
|
|
347
366
|
});
|
|
348
|
-
let
|
|
367
|
+
let _ = [], v = null;
|
|
349
368
|
try {
|
|
350
|
-
typeof PerformanceObserver < "u" && PerformanceObserver.supportedEntryTypes?.includes("longtask") && (
|
|
351
|
-
for (let t of e.getEntries())
|
|
352
|
-
startMs:
|
|
353
|
-
durationMs:
|
|
369
|
+
typeof PerformanceObserver < "u" && PerformanceObserver.supportedEntryTypes?.includes("longtask") && (v = new PerformanceObserver((e) => {
|
|
370
|
+
for (let t of e.getEntries()) _.push({
|
|
371
|
+
startMs: U(t.startTime),
|
|
372
|
+
durationMs: U(t.duration)
|
|
354
373
|
});
|
|
355
|
-
|
|
356
|
-
}),
|
|
374
|
+
_.length > me && _.splice(0, _.length - me);
|
|
375
|
+
}), v.observe({
|
|
357
376
|
type: "longtask",
|
|
358
377
|
buffered: !0
|
|
359
378
|
}));
|
|
360
379
|
} catch {
|
|
361
|
-
|
|
380
|
+
v = null;
|
|
362
381
|
}
|
|
363
|
-
let
|
|
364
|
-
let t = Array.from(document.querySelectorAll(
|
|
382
|
+
let y = [], ee = 0, x = null, S = [], C = !1, w = !1, D = () => Array.from(document.querySelectorAll(le)).filter((e) => B.has(e.getAttribute("data-flemo-status") ?? "")), O = (e) => {
|
|
383
|
+
let t = Array.from(document.querySelectorAll(b(g))).filter((e) => B.has(e.getAttribute("data-flemo-bar-status") ?? "") || e.getAttribute("data-flemo-bar-riding") === "true").length, n = Array.from(document.querySelectorAll(b(h))).filter((e) => B.has(e.getAttribute("data-flemo-status") ?? "")).length, r = Array.from(document.querySelectorAll(b(m))).filter((e) => B.has(e.getAttribute("data-flemo-status") ?? "")).length;
|
|
365
384
|
return {
|
|
366
385
|
screens: e.length,
|
|
367
386
|
bars: t,
|
|
368
387
|
decorators: n,
|
|
369
388
|
parts: r
|
|
370
389
|
};
|
|
371
|
-
},
|
|
390
|
+
}, k = (e) => {
|
|
372
391
|
let t = [];
|
|
373
392
|
for (let n of e) for (let e of Array.from(n.querySelectorAll("img"))) t.push(e);
|
|
374
393
|
return t;
|
|
375
|
-
},
|
|
394
|
+
}, A = (e) => {
|
|
376
395
|
let t = 0, n = 0;
|
|
377
396
|
for (let r of e.imagesTracked) r.complete && (t += 1, e.imagesHeld.has(r) || (n += 1));
|
|
378
397
|
return {
|
|
@@ -382,20 +401,20 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
382
401
|
heldDuringFlight: e.imagesHeld.size,
|
|
383
402
|
completedUnheld: n
|
|
384
403
|
};
|
|
385
|
-
},
|
|
386
|
-
let t =
|
|
387
|
-
if (!(!t || t.imagesTracked.size >=
|
|
404
|
+
}, j = (e) => {
|
|
405
|
+
let t = x;
|
|
406
|
+
if (!(!t || t.imagesTracked.size >= pe)) for (let n of Array.from(e)) {
|
|
388
407
|
if (!(n instanceof Element) || !t.elements.some((e) => e === n || e.contains(n))) continue;
|
|
389
408
|
let e = n instanceof HTMLImageElement ? [n] : Array.from(n.querySelectorAll("img"));
|
|
390
409
|
for (let n of e) if (!(n.complete || t.imagesTracked.has(n))) {
|
|
391
|
-
if (t.imagesTracked.size >=
|
|
410
|
+
if (t.imagesTracked.size >= pe) return;
|
|
392
411
|
t.imagesTracked.add(n), t.imagesAddedDuringFlight += 1;
|
|
393
412
|
}
|
|
394
413
|
}
|
|
395
|
-
},
|
|
396
|
-
for (let t of e.elements) for (let n of Array.from(t.querySelectorAll(`img[${
|
|
397
|
-
for (let t of e.imagesTracked) t.hasAttribute(
|
|
398
|
-
},
|
|
414
|
+
}, M = (e) => {
|
|
415
|
+
for (let t of e.elements) for (let n of Array.from(t.querySelectorAll(`img[${f}]`))) e.imagesHeld.add(n);
|
|
416
|
+
for (let t of e.imagesTracked) t.hasAttribute("data-flemo-img-hold") && e.imagesHeld.add(t);
|
|
417
|
+
}, N = (e, t) => {
|
|
399
418
|
e.releasedFrames += 1;
|
|
400
419
|
let n = !1, r = !1;
|
|
401
420
|
for (let t of e.elements) {
|
|
@@ -414,7 +433,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
414
433
|
e.lastPose.get(t) !== r && (n = !0);
|
|
415
434
|
}
|
|
416
435
|
}
|
|
417
|
-
if (!(e.releasedFrames <
|
|
436
|
+
if (!(e.releasedFrames < fe)) {
|
|
418
437
|
if (n) {
|
|
419
438
|
e.stallRunMs = 0;
|
|
420
439
|
return;
|
|
@@ -425,7 +444,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
425
444
|
}
|
|
426
445
|
e.stalledFrames += 1, e.stallRunMs += t, e.stallRunMs > e.longestStallMs && (e.longestStallMs = e.stallRunMs);
|
|
427
446
|
}
|
|
428
|
-
},
|
|
447
|
+
}, P = (e) => {
|
|
429
448
|
for (let t of e.elements) {
|
|
430
449
|
let n = t.style, r = t.getAnimations, i = e.clocks.get(t);
|
|
431
450
|
if (i !== void 0 && i.playState !== "finished") {
|
|
@@ -448,51 +467,51 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
448
467
|
i !== void 0 && i !== r && (e.evidence.playerAdvance = !0), e.lastPose.set(t, r);
|
|
449
468
|
}
|
|
450
469
|
}
|
|
451
|
-
},
|
|
452
|
-
let t = e.getAttribute(
|
|
453
|
-
return t !== null &&
|
|
454
|
-
}),
|
|
455
|
-
let e =
|
|
456
|
-
if (!e ||
|
|
470
|
+
}, ne = (e) => e.elements.some((e) => {
|
|
471
|
+
let t = e.getAttribute(H);
|
|
472
|
+
return t !== null && V.has(t);
|
|
473
|
+
}), re = () => {
|
|
474
|
+
let e = x;
|
|
475
|
+
if (!e || C) return;
|
|
457
476
|
let t = performance.now();
|
|
458
|
-
if (e.lastFrameAt !== null && e.heldGaps.length + e.releasedGaps.length <
|
|
459
|
-
let n = t - e.lastFrameAt, r =
|
|
460
|
-
(r ? e.heldGaps : e.releasedGaps).push(n), r || (
|
|
477
|
+
if (e.lastFrameAt !== null && e.heldGaps.length + e.releasedGaps.length < de) {
|
|
478
|
+
let n = t - e.lastFrameAt, r = ne(e);
|
|
479
|
+
(r ? e.heldGaps : e.releasedGaps).push(n), r || (N(e, n), e.releasedFrames === 1 && M(e));
|
|
461
480
|
}
|
|
462
|
-
if (e.lastFrameAt = t,
|
|
463
|
-
|
|
481
|
+
if (e.lastFrameAt = t, P(e), t - e.t0Ms > 1e4) {
|
|
482
|
+
S = [...e.elements], W(t, L(e));
|
|
464
483
|
return;
|
|
465
484
|
}
|
|
466
|
-
e.rafId = requestAnimationFrame(
|
|
467
|
-
},
|
|
485
|
+
e.rafId = requestAnimationFrame(re);
|
|
486
|
+
}, L = (e) => {
|
|
468
487
|
let t = /* @__PURE__ */ new Set();
|
|
469
488
|
for (let n of e.elements) {
|
|
470
|
-
let e = n.getAttribute(
|
|
471
|
-
|
|
489
|
+
let e = n.getAttribute("data-flemo-status") ?? "";
|
|
490
|
+
B.has(e) && t.add(e);
|
|
472
491
|
}
|
|
473
492
|
return [...t];
|
|
474
|
-
},
|
|
493
|
+
}, R = (e) => {
|
|
475
494
|
let t = performance.now();
|
|
476
|
-
|
|
477
|
-
let n = e.find((e) => e.getAttribute(
|
|
495
|
+
ee += 1;
|
|
496
|
+
let n = e.find((e) => e.getAttribute("data-flemo-active") === "true") ?? e[0], r = oe(n.getAttribute("data-flemo-status") ?? "") ?? "PUSH", i = null;
|
|
478
497
|
for (let t of e) {
|
|
479
|
-
let e = t.getAttribute(
|
|
480
|
-
if (e !== null &&
|
|
498
|
+
let e = t.getAttribute(H);
|
|
499
|
+
if (e !== null && V.has(e)) {
|
|
481
500
|
i = e;
|
|
482
501
|
break;
|
|
483
502
|
}
|
|
484
503
|
}
|
|
485
|
-
|
|
486
|
-
id: `flight-${
|
|
504
|
+
x = {
|
|
505
|
+
id: `flight-${ee}`,
|
|
487
506
|
kind: r,
|
|
488
507
|
routerId: n.getAttribute("data-flemo-router") ?? void 0,
|
|
489
508
|
t0Ms: t,
|
|
490
509
|
t0Iso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
491
510
|
elements: [...e],
|
|
492
|
-
participants:
|
|
511
|
+
participants: O(e),
|
|
493
512
|
holdKind: i,
|
|
494
513
|
holdReleasedAtMs: null,
|
|
495
|
-
playerGapStartIndex:
|
|
514
|
+
playerGapStartIndex: ge().__flemoPlayerGaps?.length ?? 0,
|
|
496
515
|
heldGaps: [],
|
|
497
516
|
releasedGaps: [],
|
|
498
517
|
lastFrameAt: null,
|
|
@@ -511,32 +530,32 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
511
530
|
longestStallMs: 0,
|
|
512
531
|
pausedAfterRelease: !1,
|
|
513
532
|
holdReassertedAtMs: null,
|
|
514
|
-
imagesTracked: new Set(
|
|
533
|
+
imagesTracked: new Set(k(e).filter((e) => !e.complete)),
|
|
515
534
|
imagesLoadingAtStart: 0,
|
|
516
535
|
imagesAddedDuringFlight: 0,
|
|
517
536
|
imagesHeld: /* @__PURE__ */ new Set(),
|
|
518
537
|
rafId: null
|
|
519
|
-
},
|
|
520
|
-
},
|
|
521
|
-
let n =
|
|
522
|
-
if (!
|
|
538
|
+
}, x.imagesLoadingAtStart = x.imagesTracked.size, P(x), x.rafId = requestAnimationFrame(re);
|
|
539
|
+
}, ce = (e, t) => {
|
|
540
|
+
let n = ue, r = () => {
|
|
541
|
+
if (!C) {
|
|
523
542
|
if (--n, n > 0) {
|
|
524
543
|
requestAnimationFrame(r);
|
|
525
544
|
return;
|
|
526
545
|
}
|
|
527
|
-
|
|
546
|
+
ve(e, t);
|
|
528
547
|
}
|
|
529
548
|
};
|
|
530
549
|
requestAnimationFrame(r);
|
|
531
|
-
},
|
|
532
|
-
if (
|
|
550
|
+
}, _e = () => {
|
|
551
|
+
if (x !== null || D().length > 0) return [];
|
|
533
552
|
let e = [];
|
|
534
|
-
for (let [t, n] of [[
|
|
553
|
+
for (let [t, n] of [[f, "image reveal hold"], [p, "arrival hold"]]) {
|
|
535
554
|
let r = document.querySelectorAll(`[${t}]`).length;
|
|
536
555
|
r > 0 && e.push(`${r} × ${n} (${t}) still marked at rest`);
|
|
537
556
|
}
|
|
538
557
|
return e;
|
|
539
|
-
},
|
|
558
|
+
}, ve = (e, t) => {
|
|
540
559
|
let n = [], r = !1, i = window.visualViewport?.width ?? window.innerWidth ?? 0;
|
|
541
560
|
t.forEach((e, t) => {
|
|
542
561
|
if (!(e instanceof HTMLElement) || !e.isConnected) return;
|
|
@@ -546,45 +565,45 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
546
565
|
a = t.transform ?? "", o = t.display ?? "";
|
|
547
566
|
} catch {}
|
|
548
567
|
if (o === "none") return;
|
|
549
|
-
let s = e.getAttribute(
|
|
550
|
-
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(
|
|
551
|
-
let e =
|
|
568
|
+
let s = e.getAttribute(u) === "true", c = `screen[${t}]${s ? " (active)" : ""}`;
|
|
569
|
+
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) {
|
|
570
|
+
let e = se(a);
|
|
552
571
|
e !== null && Math.abs(e) >= i * .5 && (r = !0);
|
|
553
572
|
}
|
|
554
|
-
}), e.landing.residualInlineTransforms = n, e.landing.offViewportAtRest = r, e.landing.orphanedHolds =
|
|
555
|
-
},
|
|
556
|
-
let i =
|
|
573
|
+
}), e.landing.residualInlineTransforms = n, e.landing.offViewportAtRest = r, e.landing.orphanedHolds = _e();
|
|
574
|
+
}, W = (e, t) => {
|
|
575
|
+
let i = x;
|
|
557
576
|
if (!i) return;
|
|
558
|
-
|
|
559
|
-
let a =
|
|
577
|
+
M(i), x = null, i.rafId !== null && cancelAnimationFrame(i.rafId);
|
|
578
|
+
let a = z((ge().__flemoPlayerGaps ?? []).slice(i.playerGapStartIndex)), o = {
|
|
560
579
|
id: i.id,
|
|
561
580
|
...i.routerId === void 0 ? {} : { routerId: i.routerId },
|
|
562
581
|
kind: i.kind,
|
|
563
582
|
t0: {
|
|
564
|
-
ms:
|
|
583
|
+
ms: U(i.t0Ms),
|
|
565
584
|
iso: i.t0Iso
|
|
566
585
|
},
|
|
567
586
|
t1: {
|
|
568
|
-
ms:
|
|
587
|
+
ms: U(e),
|
|
569
588
|
iso: (/* @__PURE__ */ new Date()).toISOString()
|
|
570
589
|
},
|
|
571
|
-
durationMs:
|
|
572
|
-
driver:
|
|
590
|
+
durationMs: U(e - i.t0Ms),
|
|
591
|
+
driver: ae(i.evidence),
|
|
573
592
|
participants: i.participants,
|
|
574
593
|
holds: {
|
|
575
594
|
kind: i.holdKind,
|
|
576
595
|
releasedAtMs: i.holdReleasedAtMs
|
|
577
596
|
},
|
|
578
|
-
frameSamples:
|
|
597
|
+
frameSamples: ie(i.heldGaps, i.releasedGaps),
|
|
579
598
|
motion: {
|
|
580
599
|
sampledFrames: i.releasedFrames,
|
|
581
600
|
stalledFrames: i.stalledFrames,
|
|
582
|
-
longestStallMs:
|
|
601
|
+
longestStallMs: U(i.longestStallMs),
|
|
583
602
|
pausedAfterRelease: i.pausedAfterRelease,
|
|
584
603
|
holdReassertedAtMs: i.holdReassertedAtMs,
|
|
585
604
|
tailFrames: i.tailFrames
|
|
586
605
|
},
|
|
587
|
-
images:
|
|
606
|
+
images: A(i),
|
|
588
607
|
...a ? { playerGaps: a } : {},
|
|
589
608
|
longTasks: [],
|
|
590
609
|
holdLongTasks: [],
|
|
@@ -596,34 +615,34 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
596
615
|
},
|
|
597
616
|
anomalies: []
|
|
598
617
|
};
|
|
599
|
-
|
|
600
|
-
},
|
|
601
|
-
let t =
|
|
618
|
+
y.push(o), y.length > n && y.splice(0, y.length - n), t.length === 0 && ce(o, i.elements), r && console.info(`[flemo devtools] ${o.id} ${o.kind} driver=${o.driver} ${o.durationMs}ms screens=${o.participants.screens}`);
|
|
619
|
+
}, ye = (e) => {
|
|
620
|
+
let t = x;
|
|
602
621
|
if (!t || !(e.target instanceof Element)) return;
|
|
603
|
-
let n = e.target.getAttribute(
|
|
604
|
-
n !== null &&
|
|
605
|
-
},
|
|
606
|
-
let e =
|
|
607
|
-
if (
|
|
608
|
-
if (e.some((e) =>
|
|
609
|
-
|
|
622
|
+
let n = e.target.getAttribute(H);
|
|
623
|
+
n !== null && V.has(n) && t.holdKind === null && (t.holdKind = n), n !== null && V.has(n) && t.holdReleasedAtMs !== null && t.holdReassertedAtMs === null && (t.holdReassertedAtMs = U(performance.now() - t.t0Ms)), (n === "false" || n === null) && e.oldValue !== null && V.has(e.oldValue) && t.holdReleasedAtMs === null && !ne(t) && (t.holdReleasedAtMs = U(performance.now() - t.t0Ms));
|
|
624
|
+
}, G = () => {
|
|
625
|
+
let e = D();
|
|
626
|
+
if (S.length > 0) {
|
|
627
|
+
if (e.some((e) => S.includes(e))) return;
|
|
628
|
+
S = [];
|
|
610
629
|
}
|
|
611
|
-
if (!
|
|
612
|
-
|
|
630
|
+
if (!x && e.length > 0) {
|
|
631
|
+
R(e);
|
|
613
632
|
return;
|
|
614
633
|
}
|
|
615
|
-
if (
|
|
616
|
-
|
|
634
|
+
if (x && e.length === 0) {
|
|
635
|
+
W(performance.now(), []);
|
|
617
636
|
return;
|
|
618
637
|
}
|
|
619
|
-
if (
|
|
620
|
-
},
|
|
638
|
+
if (x) for (let t of e) x.elements.includes(t) || (x.elements.push(t), j(t.querySelectorAll("img")), x.participants = O(x.elements));
|
|
639
|
+
}, K = null, q = null, J = () => {
|
|
621
640
|
let e = document.documentElement;
|
|
622
641
|
if (!e) return !1;
|
|
623
642
|
let t = new MutationObserver((e) => {
|
|
624
|
-
if (!
|
|
625
|
-
for (let t of e) t.type === "attributes" && t.attributeName ===
|
|
626
|
-
|
|
643
|
+
if (!C) {
|
|
644
|
+
for (let t of e) t.type === "attributes" && t.attributeName === H ? ye(t) : t.type === "childList" && t.addedNodes.length > 0 && j(t.addedNodes);
|
|
645
|
+
G();
|
|
627
646
|
}
|
|
628
647
|
});
|
|
629
648
|
try {
|
|
@@ -633,31 +652,31 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
633
652
|
attributes: !0,
|
|
634
653
|
attributeOldValue: !0,
|
|
635
654
|
attributeFilter: [
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
655
|
+
l,
|
|
656
|
+
u,
|
|
657
|
+
H
|
|
639
658
|
]
|
|
640
659
|
});
|
|
641
660
|
} catch {
|
|
642
661
|
return !1;
|
|
643
662
|
}
|
|
644
|
-
return
|
|
663
|
+
return K = t, G(), !0;
|
|
645
664
|
};
|
|
646
|
-
if (
|
|
665
|
+
if (!J()) {
|
|
647
666
|
let e = () => {
|
|
648
|
-
|
|
667
|
+
q = null, C || J();
|
|
649
668
|
};
|
|
650
|
-
|
|
669
|
+
q = e, document.addEventListener("DOMContentLoaded", e, { once: !0 });
|
|
651
670
|
}
|
|
652
|
-
let
|
|
653
|
-
let t =
|
|
671
|
+
let Y = (e) => {
|
|
672
|
+
let t = _.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;
|
|
654
673
|
return {
|
|
655
674
|
released: t.filter((e) => e.startMs + e.durationMs > n),
|
|
656
675
|
held: t.filter((e) => e.startMs + e.durationMs <= n)
|
|
657
676
|
};
|
|
658
|
-
},
|
|
659
|
-
let e = performance.now(), n =
|
|
660
|
-
let t =
|
|
677
|
+
}, X = () => {
|
|
678
|
+
let e = performance.now(), n = y.map((e) => {
|
|
679
|
+
let t = Y(e), n = {
|
|
661
680
|
...e,
|
|
662
681
|
longTasks: t.released,
|
|
663
682
|
holdLongTasks: t.held,
|
|
@@ -681,47 +700,47 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
681
700
|
motion: n.motion,
|
|
682
701
|
images: n.images
|
|
683
702
|
}), n;
|
|
684
|
-
}), r =
|
|
703
|
+
}), r = x;
|
|
685
704
|
if (!r) return n;
|
|
686
705
|
let i = e - r.t0Ms > t, o = {
|
|
687
706
|
id: `${r.id} (in flight)`,
|
|
688
707
|
...r.routerId === void 0 ? {} : { routerId: r.routerId },
|
|
689
708
|
kind: r.kind,
|
|
690
709
|
t0: {
|
|
691
|
-
ms:
|
|
710
|
+
ms: U(r.t0Ms),
|
|
692
711
|
iso: r.t0Iso
|
|
693
712
|
},
|
|
694
713
|
t1: {
|
|
695
|
-
ms:
|
|
714
|
+
ms: U(e),
|
|
696
715
|
iso: (/* @__PURE__ */ new Date()).toISOString()
|
|
697
716
|
},
|
|
698
|
-
durationMs:
|
|
699
|
-
driver:
|
|
717
|
+
durationMs: U(e - r.t0Ms),
|
|
718
|
+
driver: ae(r.evidence),
|
|
700
719
|
participants: r.participants,
|
|
701
720
|
holds: {
|
|
702
721
|
kind: r.holdKind,
|
|
703
722
|
releasedAtMs: r.holdReleasedAtMs
|
|
704
723
|
},
|
|
705
|
-
frameSamples:
|
|
724
|
+
frameSamples: ie(r.heldGaps, r.releasedGaps),
|
|
706
725
|
motion: {
|
|
707
726
|
sampledFrames: r.releasedFrames,
|
|
708
727
|
stalledFrames: r.stalledFrames,
|
|
709
|
-
longestStallMs:
|
|
728
|
+
longestStallMs: U(r.longestStallMs),
|
|
710
729
|
pausedAfterRelease: r.pausedAfterRelease,
|
|
711
730
|
holdReassertedAtMs: r.holdReassertedAtMs,
|
|
712
731
|
tailFrames: r.tailFrames
|
|
713
732
|
},
|
|
714
|
-
images:
|
|
733
|
+
images: A(r),
|
|
715
734
|
longTasks: [],
|
|
716
735
|
holdLongTasks: [],
|
|
717
736
|
landing: {
|
|
718
737
|
residualInlineTransforms: [],
|
|
719
738
|
offViewportAtRest: !1,
|
|
720
|
-
stuckStatuses: i ?
|
|
739
|
+
stuckStatuses: i ? L(r) : [],
|
|
721
740
|
orphanedHolds: []
|
|
722
741
|
},
|
|
723
742
|
anomalies: []
|
|
724
|
-
}, s =
|
|
743
|
+
}, s = Y(o);
|
|
725
744
|
return o.longTasks = s.released, o.holdLongTasks = s.held, o.anomalies = a({
|
|
726
745
|
t0Ms: o.t0.ms,
|
|
727
746
|
t1Ms: o.t1.ms,
|
|
@@ -735,16 +754,10 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
735
754
|
motion: o.motion,
|
|
736
755
|
images: o.images
|
|
737
756
|
}), [...n, o];
|
|
738
|
-
},
|
|
739
|
-
|
|
740
|
-
return (e === "session" ? sessionStorage : localStorage).getItem(t);
|
|
741
|
-
} catch {
|
|
742
|
-
return null;
|
|
743
|
-
}
|
|
744
|
-
}, he = () => {
|
|
745
|
-
let e = x(), t = { ...e };
|
|
757
|
+
}, be = () => {
|
|
758
|
+
let e = F(), t = { ...e };
|
|
746
759
|
for (let [n, r] of Object.entries(c)) n in e || (t[`${n} (at attach, since cleared)`] = r);
|
|
747
|
-
let n =
|
|
760
|
+
let n = I(t), r = T(d), i = X(), a = x;
|
|
748
761
|
return {
|
|
749
762
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
750
763
|
version: "2",
|
|
@@ -753,57 +766,50 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
753
766
|
active: t,
|
|
754
767
|
warnings: n
|
|
755
768
|
},
|
|
756
|
-
|
|
757
|
-
demotion: me("local", "flemo:motion-driver"),
|
|
758
|
-
forcePin: i
|
|
759
|
-
},
|
|
760
|
-
flights: u,
|
|
769
|
+
flights: i,
|
|
761
770
|
anomalies: o({
|
|
762
|
-
forcePin: i,
|
|
763
|
-
legacyLocalForcePin: t[_] ?? null,
|
|
764
|
-
clearedForcePin: a,
|
|
765
771
|
emulationSuspected: r.emulationSuspected,
|
|
766
772
|
platform: r.platform,
|
|
767
|
-
stuckFlightOpen:
|
|
768
|
-
flightAnomalies:
|
|
773
|
+
stuckFlightOpen: a !== null && performance.now() - a.t0Ms > 1e4,
|
|
774
|
+
flightAnomalies: i.map((e) => e.anomalies)
|
|
769
775
|
}),
|
|
770
776
|
blindSpots: [...s],
|
|
771
|
-
judgingProtocol: [...
|
|
777
|
+
judgingProtocol: [...E]
|
|
772
778
|
};
|
|
773
|
-
},
|
|
774
|
-
if (!
|
|
775
|
-
if (
|
|
776
|
-
let e =
|
|
779
|
+
}, xe = () => {
|
|
780
|
+
if (!C) {
|
|
781
|
+
if (C = !0, K?.disconnect(), q !== null && (document.removeEventListener("DOMContentLoaded", q), q = null), v?.disconnect(), x?.rafId != null && cancelAnimationFrame(x.rafId), x = null, w) {
|
|
782
|
+
let e = ge();
|
|
777
783
|
e.flemo?.__flemoDevtools === !0 && delete e.flemo;
|
|
778
784
|
}
|
|
779
|
-
|
|
785
|
+
he = null;
|
|
780
786
|
}
|
|
781
|
-
},
|
|
782
|
-
detach:
|
|
783
|
-
report:
|
|
787
|
+
}, Se = {
|
|
788
|
+
detach: xe,
|
|
789
|
+
report: be
|
|
784
790
|
};
|
|
785
791
|
if (i) {
|
|
786
|
-
let e =
|
|
792
|
+
let e = ge(), t = e.flemo;
|
|
787
793
|
(t === void 0 || t?.__flemoDevtools === !0) && (e.flemo = {
|
|
788
794
|
__flemoDevtools: !0,
|
|
789
|
-
report:
|
|
790
|
-
flights:
|
|
791
|
-
detach:
|
|
792
|
-
},
|
|
795
|
+
report: be,
|
|
796
|
+
flights: X,
|
|
797
|
+
detach: xe
|
|
798
|
+
}, w = !0);
|
|
793
799
|
}
|
|
794
|
-
return
|
|
795
|
-
},
|
|
800
|
+
return he = Se, Se;
|
|
801
|
+
}, ve = "http://www.w3.org/2000/svg", W = (e, t, n) => {
|
|
796
802
|
let r = document.createElement(e);
|
|
797
803
|
return t !== void 0 && (r.className = t), n !== void 0 && (r.textContent = n), r;
|
|
798
|
-
},
|
|
799
|
-
let n = document.createElementNS(
|
|
804
|
+
}, ye = (e, t) => {
|
|
805
|
+
let n = document.createElementNS(ve, e);
|
|
800
806
|
for (let [e, r] of Object.entries(t)) n.setAttribute(e, r);
|
|
801
807
|
return n;
|
|
802
808
|
}, G = (e) => {
|
|
803
809
|
for (; e.firstChild !== null;) e.removeChild(e.firstChild);
|
|
804
810
|
}, K = (e, t) => {
|
|
805
811
|
e.textContent !== t && (e.textContent = t);
|
|
806
|
-
}, q = (e) => e == null || e === "" ? "—" : String(e), J = (e) => typeof e == "number" && Number.isFinite(e) ? `${Math.round(e)}ms` : "—", Y = (e) => typeof e == "number" && Number.isFinite(e) ? `${Math.round(e * 10) / 10}ms` : "—", X = (e) => typeof e == "number" && Number.isFinite(e) ? String(e) : "—",
|
|
812
|
+
}, q = (e) => e == null || e === "" ? "—" : String(e), J = (e) => typeof e == "number" && Number.isFinite(e) ? `${Math.round(e)}ms` : "—", Y = (e) => typeof e == "number" && Number.isFinite(e) ? `${Math.round(e * 10) / 10}ms` : "—", X = (e) => typeof e == "number" && Number.isFinite(e) ? String(e) : "—", be = (e) => e === !0 ? "yes" : e === !1 ? "no" : "—", xe = (e) => {
|
|
807
813
|
let t = e?.environment;
|
|
808
814
|
if (!t) return "—";
|
|
809
815
|
let n = t.viewport, r = n && typeof n.width == "number" && typeof n.height == "number" ? `${Math.round(n.width)}×${Math.round(n.height)}` : "—";
|
|
@@ -813,36 +819,36 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
813
819
|
r,
|
|
814
820
|
`rAF ${Y(t.rafCadence?.medianGapMs)}`
|
|
815
821
|
].join(" · ");
|
|
816
|
-
},
|
|
822
|
+
}, Se = (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(",")}`, Ce = (e) => {
|
|
817
823
|
let t = e?.released?.gaps;
|
|
818
824
|
if (!Array.isArray(t)) return null;
|
|
819
825
|
let n = t.filter((e) => typeof e == "number" && Number.isFinite(e));
|
|
820
826
|
return n.length >= 2 ? n : null;
|
|
821
|
-
},
|
|
822
|
-
let i =
|
|
823
|
-
i.appendChild(
|
|
827
|
+
}, we = "\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.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", Te = 48, Z = (e, t, n, r) => {
|
|
828
|
+
let i = W("div", "kv");
|
|
829
|
+
i.appendChild(W("span", "k", t)), i.appendChild(W("span", r ? `v ${r}` : "v", n)), e.appendChild(i);
|
|
824
830
|
}, Q = (e, t) => {
|
|
825
|
-
let n =
|
|
826
|
-
return n.appendChild(
|
|
831
|
+
let n = W("section", "section");
|
|
832
|
+
return n.appendChild(W("h2", void 0, t)), e.appendChild(n), n;
|
|
827
833
|
}, $ = (e, t, n = "li") => {
|
|
828
|
-
e.appendChild(
|
|
829
|
-
},
|
|
834
|
+
e.appendChild(W("div", n, t));
|
|
835
|
+
}, Ee = (e, t) => {
|
|
830
836
|
G(e);
|
|
831
|
-
for (let n of t?.overrides?.warnings ?? []) e.appendChild(
|
|
832
|
-
for (let n of t?.anomalies ?? []) e.appendChild(
|
|
833
|
-
for (let [n, r] of Object.entries(t?.overrides?.active ?? {})) e.appendChild(
|
|
834
|
-
},
|
|
837
|
+
for (let n of t?.overrides?.warnings ?? []) e.appendChild(W("span", "chip warn", q(n)));
|
|
838
|
+
for (let n of t?.anomalies ?? []) e.appendChild(W("span", "chip bad", q(n)));
|
|
839
|
+
for (let [n, r] of Object.entries(t?.overrides?.active ?? {})) e.appendChild(W("span", "chip", `${n}=${String(r)}`));
|
|
840
|
+
}, De = (e, t, n, r) => {
|
|
835
841
|
if (G(e), t.length === 0) {
|
|
836
842
|
$(e, "no flights recorded yet — navigate once", "li dim");
|
|
837
843
|
return;
|
|
838
844
|
}
|
|
839
845
|
for (let i = t.length - 1; i >= 0; --i) {
|
|
840
|
-
let a = t[i], o = q(a?.id), s =
|
|
841
|
-
s.type = "button", s.setAttribute("data-flight-id", o), s.setAttribute("aria-selected", String(o === n)), s.appendChild(
|
|
846
|
+
let a = t[i], o = q(a?.id), s = W("button", "row");
|
|
847
|
+
s.type = "button", s.setAttribute("data-flight-id", o), s.setAttribute("aria-selected", String(o === n)), s.appendChild(W("span", "kind", q(a?.kind))), s.appendChild(W("span", "driver", q(a?.driver))), s.appendChild(W("span", "dur", J(a?.durationMs))), s.appendChild(W("span", "screens", `${X(a?.participants?.screens)} scr`));
|
|
842
848
|
let c = a?.anomalies?.length ?? 0;
|
|
843
|
-
s.appendChild(
|
|
849
|
+
s.appendChild(W("span", c > 0 ? "n bad" : "n", String(c))), s.addEventListener("click", () => r(o)), e.appendChild(s);
|
|
844
850
|
}
|
|
845
|
-
},
|
|
851
|
+
}, Oe = (e, t, n) => {
|
|
846
852
|
if (!n) {
|
|
847
853
|
Z(e, t, "—");
|
|
848
854
|
return;
|
|
@@ -853,21 +859,21 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
853
859
|
`max ${Y(n.maxGapMs)}`
|
|
854
860
|
];
|
|
855
861
|
typeof n.over30Count == "number" && r.push(`>30ms ×${n.over30Count}`), Z(e, t, r.join(" · "));
|
|
856
|
-
},
|
|
857
|
-
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 =
|
|
862
|
+
}, ke = (e) => {
|
|
863
|
+
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 = ye("svg", {
|
|
858
864
|
class: "spark",
|
|
859
865
|
viewBox: "0 0 100 28",
|
|
860
866
|
preserveAspectRatio: "none",
|
|
861
867
|
"aria-hidden": "true"
|
|
862
868
|
});
|
|
863
|
-
return a.appendChild(
|
|
869
|
+
return a.appendChild(ye("polyline", {
|
|
864
870
|
points: i,
|
|
865
871
|
fill: "none",
|
|
866
872
|
stroke: "currentColor",
|
|
867
873
|
"stroke-width": "1",
|
|
868
874
|
"vector-effect": "non-scaling-stroke"
|
|
869
875
|
})), a;
|
|
870
|
-
},
|
|
876
|
+
}, Ae = (e, t) => {
|
|
871
877
|
let n = t.longTasks ?? [], r = t.holdLongTasks ?? [];
|
|
872
878
|
if (n.length === 0 && r.length === 0) {
|
|
873
879
|
$(e, "none", "li dim");
|
|
@@ -876,7 +882,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
876
882
|
let i = (e) => `${J(e?.startMs)} + ${J(e?.durationMs)}`;
|
|
877
883
|
for (let t of n) $(e, i(t), "li bad");
|
|
878
884
|
for (let t of r) $(e, `${i(t)} (absorbed by hold)`, "li dim");
|
|
879
|
-
},
|
|
885
|
+
}, je = (e, t) => {
|
|
880
886
|
if (G(e), !t) {
|
|
881
887
|
$(e, "select a flight", "li dim");
|
|
882
888
|
return;
|
|
@@ -884,17 +890,17 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
884
890
|
let n = Q(e, "timing");
|
|
885
891
|
Z(n, "id", q(t.id)), Z(n, "kind / driver", `${q(t.kind)} · ${q(t.driver)}`), Z(n, "router", q(t.routerId)), Z(n, "t0", q(t.t0?.iso)), Z(n, "duration", J(t.durationMs)), Z(n, "participants", `${X(t.participants?.screens)} screens · ${X(t.participants?.bars)} bars · ${X(t.participants?.decorators)} decorators · ${X(t.participants?.parts)} parts`), Z(n, "hold", `${q(t.holds?.kind)} · released ${J(t.holds?.releasedAtMs)}`);
|
|
886
892
|
let r = Q(e, "frames");
|
|
887
|
-
|
|
888
|
-
let i =
|
|
889
|
-
i && r.appendChild(
|
|
893
|
+
Oe(r, "held (absorbed)", t.frameSamples?.held), Oe(r, "released (visible)", t.frameSamples?.released), t.playerGaps && Z(r, "player mirror", `max ${Y(t.playerGaps.maxMs)} · >30ms ×${X(t.playerGaps.over30Count)}`);
|
|
894
|
+
let i = Ce(t.frameSamples);
|
|
895
|
+
i && r.appendChild(ke(i));
|
|
890
896
|
let a = Q(e, "motion (did it move)"), o = t.motion?.longestStallMs, s = t.motion?.holdReassertedAtMs;
|
|
891
|
-
Z(a, "released frames", X(t.motion?.sampledFrames)), Z(a, "stalled frames", X(t.motion?.stalledFrames), (t.motion?.stalledFrames ?? 0) > 0 ? "bad" : void 0), Z(a, "longest stall", J(o), (o ?? 0) >=
|
|
897
|
+
Z(a, "released frames", X(t.motion?.sampledFrames)), Z(a, "stalled frames", X(t.motion?.stalledFrames), (t.motion?.stalledFrames ?? 0) > 0 ? "bad" : void 0), Z(a, "longest stall", J(o), (o ?? 0) >= Te ? "bad" : void 0), Z(a, "paused after release", be(t.motion?.pausedAfterRelease), t.motion?.pausedAfterRelease === !0 ? "bad" : void 0), Z(a, "hold re-asserted", s == null ? "no" : J(s), typeof s == "number" ? "bad" : void 0);
|
|
892
898
|
let c = Q(e, "images"), l = t.images?.completedDuringFlight ?? 0, u = t.images?.heldDuringFlight ?? 0, d = t.images?.completedUnheld, f = typeof d == "number" ? d > 0 : l > u;
|
|
893
|
-
Z(c, "loading at t0", X(t.images?.loadingAtStart)), Z(c, "added mid-flight", X(t.images?.addedDuringFlight)), Z(c, "completed mid-flight", X(t.images?.completedDuringFlight), f ? "bad" : void 0), Z(c, "held by the engine", X(t.images?.heldDuringFlight)), Z(c, "completed without hold", X(d), f ? "bad" : void 0),
|
|
899
|
+
Z(c, "loading at t0", X(t.images?.loadingAtStart)), Z(c, "added mid-flight", X(t.images?.addedDuringFlight)), Z(c, "completed mid-flight", X(t.images?.completedDuringFlight), f ? "bad" : void 0), Z(c, "held by the engine", X(t.images?.heldDuringFlight)), Z(c, "completed without hold", X(d), f ? "bad" : void 0), Ae(Q(e, "long tasks"), t);
|
|
894
900
|
let p = Q(e, "landing"), m = t.landing?.residualInlineTransforms ?? [];
|
|
895
901
|
if (m.length === 0) Z(p, "inline residue", "clean");
|
|
896
902
|
else for (let e of m) Z(p, "inline residue", q(e));
|
|
897
|
-
Z(p, "off-viewport at rest",
|
|
903
|
+
Z(p, "off-viewport at rest", be(t.landing?.offViewportAtRest));
|
|
898
904
|
let h = t.landing?.stuckStatuses ?? [];
|
|
899
905
|
Z(p, "stuck statuses", h.length === 0 ? "none" : h.join(", "));
|
|
900
906
|
let g = t.landing?.orphanedHolds ?? [];
|
|
@@ -906,152 +912,152 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
|
|
|
906
912
|
return;
|
|
907
913
|
}
|
|
908
914
|
for (let e of v) $(_, q(e), "li bad");
|
|
909
|
-
},
|
|
915
|
+
}, Me = (e, t) => {
|
|
910
916
|
G(e);
|
|
911
917
|
for (let n of t ?? []) $(e, q(n));
|
|
912
|
-
},
|
|
913
|
-
if (
|
|
914
|
-
if (typeof document > "u") return { detach:
|
|
918
|
+
}, Ne = v.map((e) => b(c) + ee(l, e)).join(","), Pe = 320, Fe = 2e3, Ie = 120, Le = "Copy report JSON", Re = () => {}, ze = null, Be = (e = {}) => {
|
|
919
|
+
if (ze) return ze;
|
|
920
|
+
if (typeof document > "u") return { detach: Re };
|
|
915
921
|
let t = !1, n, r = window.flemo;
|
|
916
922
|
e.recorder ? n = e.recorder : r?.__flemoDevtools === !0 && typeof r.report == "function" ? n = {
|
|
917
923
|
report: r.report,
|
|
918
|
-
detach:
|
|
919
|
-
} : (n =
|
|
920
|
-
let i =
|
|
921
|
-
i.setAttribute(
|
|
922
|
-
let a = i.attachShadow({ mode: "open" }), o =
|
|
923
|
-
o.textContent =
|
|
924
|
-
let s =
|
|
924
|
+
detach: Re
|
|
925
|
+
} : (n = _e(), t = !0);
|
|
926
|
+
let i = W("div");
|
|
927
|
+
i.setAttribute(_, ""), i.style.position = "fixed", i.style.top = "0", i.style.left = "0", i.style.width = "0", i.style.height = "0", i.style.zIndex = "2147483000";
|
|
928
|
+
let a = i.attachShadow({ mode: "open" }), o = W("style");
|
|
929
|
+
o.textContent = we, a.appendChild(o);
|
|
930
|
+
let s = W("div", "root");
|
|
925
931
|
a.appendChild(s);
|
|
926
|
-
let c =
|
|
932
|
+
let c = W("button", "toggle");
|
|
927
933
|
c.type = "button", c.setAttribute("data-corner", e.position ?? "bottom-right"), c.setAttribute("aria-label", "flemo devtools");
|
|
928
|
-
let l =
|
|
929
|
-
u.hidden = !0, c.appendChild(
|
|
930
|
-
let d =
|
|
934
|
+
let l = W("span", "count", "0"), u = W("span", "dot");
|
|
935
|
+
u.hidden = !0, c.appendChild(W("span", "mark", "flemo")), c.appendChild(l), c.appendChild(u);
|
|
936
|
+
let d = W("section", "panel");
|
|
931
937
|
d.hidden = !0;
|
|
932
|
-
let f =
|
|
938
|
+
let f = W("div", "grip");
|
|
933
939
|
f.setAttribute("role", "separator"), f.setAttribute("aria-label", "Resize flemo devtools panel");
|
|
934
|
-
let p =
|
|
940
|
+
let p = W("header", "head"), m = W("div", "env", "—"), h = W("button", "act", Le);
|
|
935
941
|
h.type = "button";
|
|
936
|
-
let g =
|
|
942
|
+
let g = W("button", "act", "Close");
|
|
937
943
|
g.type = "button";
|
|
938
|
-
let
|
|
939
|
-
|
|
940
|
-
let
|
|
941
|
-
p.appendChild(m), p.appendChild(
|
|
942
|
-
let
|
|
943
|
-
|
|
944
|
-
let S =
|
|
945
|
-
C.appendChild(
|
|
946
|
-
let
|
|
947
|
-
C.appendChild(
|
|
948
|
-
let
|
|
944
|
+
let v = W("button", "act", "Detach");
|
|
945
|
+
v.type = "button";
|
|
946
|
+
let y = W("div", "chips");
|
|
947
|
+
p.appendChild(m), p.appendChild(W("div", "spacer")), p.appendChild(h), p.appendChild(g), p.appendChild(v), p.appendChild(y);
|
|
948
|
+
let b = W("div", "body"), ee = W("div", "list"), x = W("div", "detail");
|
|
949
|
+
b.appendChild(ee), b.appendChild(x);
|
|
950
|
+
let S = W("div", "foot"), C = W("details");
|
|
951
|
+
C.appendChild(W("summary", void 0, "What this cannot see"));
|
|
952
|
+
let te = W("div");
|
|
953
|
+
C.appendChild(te), S.appendChild(C), d.appendChild(f), d.appendChild(p), d.appendChild(b), d.appendChild(S), s.appendChild(c), s.appendChild(d);
|
|
954
|
+
let w = !1, T = e.initialOpen === !0, E = null, O = "", k = "", A = "", j = !1, M = 0, N = 0, P = (e) => Math.min(Math.max(e, Ie), Math.max(Ie, window.innerHeight * .9)), ne = () => {
|
|
949
955
|
try {
|
|
950
|
-
let e = sessionStorage.getItem(
|
|
956
|
+
let e = sessionStorage.getItem(D);
|
|
951
957
|
if (e === null) return null;
|
|
952
958
|
let t = Number.parseFloat(e);
|
|
953
959
|
return Number.isFinite(t) ? t : null;
|
|
954
960
|
} catch {
|
|
955
961
|
return null;
|
|
956
962
|
}
|
|
957
|
-
},
|
|
963
|
+
}, re = (e) => {
|
|
958
964
|
try {
|
|
959
|
-
sessionStorage.setItem(
|
|
965
|
+
sessionStorage.setItem(D, String(Math.round(e)));
|
|
960
966
|
} catch {}
|
|
961
|
-
}, F =
|
|
967
|
+
}, F = P(ne() ?? window.innerHeight * .4);
|
|
962
968
|
d.style.height = `${Math.round(F)}px`;
|
|
963
|
-
let I = () => document.querySelector(
|
|
969
|
+
let I = () => document.querySelector(Ne) !== null, L = () => {
|
|
964
970
|
try {
|
|
965
971
|
return n.report();
|
|
966
972
|
} catch {
|
|
967
973
|
return null;
|
|
968
974
|
}
|
|
969
|
-
},
|
|
970
|
-
e !==
|
|
971
|
-
},
|
|
975
|
+
}, R = (e) => {
|
|
976
|
+
e !== E && (E = e, z());
|
|
977
|
+
}, ie = () => {
|
|
972
978
|
let e = L(), t = e?.flights ?? [];
|
|
973
979
|
K(l, String(t.length));
|
|
974
980
|
let n = t.some((e) => (e?.anomalies?.length ?? 0) > 0);
|
|
975
|
-
if (u.hidden = !n, d.hidden = !
|
|
976
|
-
K(m,
|
|
981
|
+
if (u.hidden = !n, d.hidden = !T, !T) return;
|
|
982
|
+
K(m, xe(e));
|
|
977
983
|
let r = JSON.stringify([
|
|
978
984
|
e?.overrides?.warnings ?? [],
|
|
979
985
|
e?.anomalies ?? [],
|
|
980
986
|
e?.overrides?.active ?? {}
|
|
981
987
|
]);
|
|
982
|
-
r !==
|
|
983
|
-
let i =
|
|
984
|
-
i !== O && (O = i,
|
|
985
|
-
let a = t.find((e) => e?.id ===
|
|
986
|
-
o !==
|
|
988
|
+
r !== A && (A = r, Ee(y, e)), E === null && t.length > 0 && (E = t[t.length - 1]?.id ?? null);
|
|
989
|
+
let i = Se(t, E);
|
|
990
|
+
i !== O && (O = i, De(ee, t, E, R));
|
|
991
|
+
let a = t.find((e) => e?.id === E) ?? null, o = JSON.stringify(a);
|
|
992
|
+
o !== k && (k = o, je(x, a)), j || (j = !0, Me(te, e?.blindSpots));
|
|
987
993
|
};
|
|
988
|
-
function
|
|
989
|
-
|
|
994
|
+
function z() {
|
|
995
|
+
w || I() || ie();
|
|
990
996
|
}
|
|
991
|
-
function
|
|
992
|
-
|
|
997
|
+
function ae() {
|
|
998
|
+
M = 0, z(), oe();
|
|
993
999
|
}
|
|
994
|
-
function
|
|
995
|
-
|
|
1000
|
+
function oe() {
|
|
1001
|
+
M = window.setTimeout(ae, T ? Pe : Fe);
|
|
996
1002
|
}
|
|
997
|
-
let
|
|
998
|
-
window.clearTimeout(
|
|
999
|
-
},
|
|
1000
|
-
|
|
1003
|
+
let se = () => {
|
|
1004
|
+
window.clearTimeout(M), oe();
|
|
1005
|
+
}, ce = (e) => {
|
|
1006
|
+
T = e, se(), z();
|
|
1001
1007
|
};
|
|
1002
|
-
c.addEventListener("click", () =>
|
|
1003
|
-
let
|
|
1004
|
-
if (!
|
|
1008
|
+
c.addEventListener("click", () => ce(!T)), g.addEventListener("click", () => ce(!1)), v.addEventListener("click", () => de());
|
|
1009
|
+
let B = () => {
|
|
1010
|
+
if (!w) {
|
|
1005
1011
|
if (I()) {
|
|
1006
|
-
window.clearTimeout(
|
|
1012
|
+
window.clearTimeout(N), N = window.setTimeout(B, Pe);
|
|
1007
1013
|
return;
|
|
1008
1014
|
}
|
|
1009
|
-
K(h, "Copied ✓"), window.clearTimeout(
|
|
1015
|
+
K(h, "Copied ✓"), window.clearTimeout(N), N = window.setTimeout(V, 1200);
|
|
1010
1016
|
}
|
|
1011
1017
|
};
|
|
1012
|
-
function
|
|
1018
|
+
function V() {
|
|
1013
1019
|
if (I()) {
|
|
1014
|
-
|
|
1020
|
+
N = window.setTimeout(V, Pe);
|
|
1015
1021
|
return;
|
|
1016
1022
|
}
|
|
1017
|
-
|
|
1023
|
+
N = 0, K(h, Le);
|
|
1018
1024
|
}
|
|
1019
|
-
let
|
|
1020
|
-
if (
|
|
1025
|
+
let le = (e) => {
|
|
1026
|
+
if (w) return;
|
|
1021
1027
|
if (I()) {
|
|
1022
|
-
window.clearTimeout(
|
|
1028
|
+
window.clearTimeout(N), N = window.setTimeout(() => le(e), Pe);
|
|
1023
1029
|
return;
|
|
1024
1030
|
}
|
|
1025
|
-
let t =
|
|
1031
|
+
let t = W("textarea");
|
|
1026
1032
|
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();
|
|
1027
1033
|
let n = document;
|
|
1028
1034
|
try {
|
|
1029
1035
|
n.execCommand?.("copy");
|
|
1030
1036
|
} catch {}
|
|
1031
|
-
t.remove(),
|
|
1037
|
+
t.remove(), B();
|
|
1032
1038
|
};
|
|
1033
1039
|
h.addEventListener("click", () => {
|
|
1034
1040
|
let e = JSON.stringify(L(), null, 2), t = navigator.clipboard;
|
|
1035
1041
|
if (t && typeof t.writeText == "function") {
|
|
1036
|
-
t.writeText(e).then(
|
|
1042
|
+
t.writeText(e).then(B, () => le(e));
|
|
1037
1043
|
return;
|
|
1038
1044
|
}
|
|
1039
|
-
|
|
1045
|
+
le(e);
|
|
1040
1046
|
});
|
|
1041
|
-
let
|
|
1042
|
-
F =
|
|
1043
|
-
},
|
|
1044
|
-
window.removeEventListener("pointermove",
|
|
1047
|
+
let H = (e) => {
|
|
1048
|
+
F = P(window.innerHeight - e.clientY), d.style.height = `${Math.round(F)}px`;
|
|
1049
|
+
}, ue = () => {
|
|
1050
|
+
window.removeEventListener("pointermove", H), window.removeEventListener("pointerup", ue), re(F);
|
|
1045
1051
|
};
|
|
1046
1052
|
f.addEventListener("pointerdown", (e) => {
|
|
1047
|
-
e.preventDefault(), window.addEventListener("pointermove",
|
|
1053
|
+
e.preventDefault(), window.addEventListener("pointermove", H), window.addEventListener("pointerup", ue);
|
|
1048
1054
|
});
|
|
1049
|
-
function
|
|
1050
|
-
|
|
1055
|
+
function de() {
|
|
1056
|
+
w || (w = !0, window.clearTimeout(M), M = 0, window.clearTimeout(N), N = 0, window.removeEventListener("pointermove", H), window.removeEventListener("pointerup", ue), i.remove(), t && n.detach(), ze = null);
|
|
1051
1057
|
}
|
|
1052
|
-
document.body.appendChild(i),
|
|
1053
|
-
let
|
|
1054
|
-
return
|
|
1058
|
+
document.body.appendChild(i), z(), oe();
|
|
1059
|
+
let fe = { detach: de };
|
|
1060
|
+
return ze = fe, fe;
|
|
1055
1061
|
};
|
|
1056
1062
|
//#endregion
|
|
1057
|
-
export { s as BLIND_SPOTS,
|
|
1063
|
+
export { s as BLIND_SPOTS, k as CORE_FLAGS, O as DEVTOOLS_OWNED_FLAGS, A as FLAG_REGISTRY, e as LONG_GAP_MS, i as MID_FLIGHT_TASK_MS, n as OPENING_WINDOW_LEAD_MS, r as OPENING_WINDOW_TAIL_MS, D as PANEL_HEIGHT_KEY, ce as REPORT_SCHEMA_VERSION, j as RETIRED_FLAGS, M as RETIRED_MARKER, t as STUCK_STATUS_MS, Be as attachDevtoolsPanel, _e as attachFlightRecorder, T as captureEnvironment, ae as classifyDriver, ie as computeFrameStats, R as computePhaseStats, z as computePlayerGapStats, a as deriveFlightAnomalies, I as deriveOverrideWarnings, o as deriveReportAnomalies, S as detectEngine, C as isEmulationSuspected, oe as kindFromStatus, se as parseTranslateX, te as sampleRafCadence, F as snapshotOverrides };
|