@specific.dev/spectest 0.36.0 → 0.36.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.js +55 -15
- package/package.json +1 -1
package/dist/browser.js
CHANGED
|
@@ -305,15 +305,29 @@ const RRWEB_BOOTSTRAP = `
|
|
|
305
305
|
// src points at a same-origin URL (e.g. next/font's
|
|
306
306
|
// /_next/static/media/*.woff2) is unreachable at replay time and the
|
|
307
307
|
// page silently falls back to a system font. collectFonts above won't
|
|
308
|
-
// help (FontFace-API fonts only), so inline the bytes ourselves:
|
|
309
|
-
//
|
|
310
|
-
//
|
|
308
|
+
// help (FontFace-API fonts only), so inline the bytes ourselves: fetch
|
|
309
|
+
// each url() (same-origin -> allowed, and the page already trusts the
|
|
310
|
+
// in-VM CA), rewrite the rule's src to a data:
|
|
311
311
|
// URI, then take a fresh full snapshot so the now-self-contained CSS
|
|
312
312
|
// is captured. Plain string ops, no regex — this whole script ships
|
|
313
313
|
// inside a TS template literal where regex backslashes get mangled.
|
|
314
|
+
//
|
|
315
|
+
// Do NOT start this scan from document.fonts.ready. This script runs at
|
|
316
|
+
// document-start. At that moment the font set is idle, so Chrome settles
|
|
317
|
+
// that first ready promise immediately, before the parser has registered
|
|
318
|
+
// one stylesheet. The scan then saw 0 @font-face rules, and a one-shot
|
|
319
|
+
// latch stopped it from looking again, so no font was ever inlined.
|
|
320
|
+
// (Found on run_03j0mxtvp6x0p16d9y83e: every next/font face fell back.
|
|
321
|
+
// The diagnostics were invisible too, because rrweb's console plugin
|
|
322
|
+
// only patches console at the load event.)
|
|
323
|
+
//
|
|
324
|
+
// Two triggers instead: the load event, by which all render-blocking CSS
|
|
325
|
+
// is parsed, and each \`loadingdone\` on document.fonts, which catches CSS
|
|
326
|
+
// added later by an HMR update or a client-side route change. The scan
|
|
327
|
+
// skips a rule it already inlined, so repeated triggers are cheap.
|
|
314
328
|
(function () {
|
|
315
|
-
if (window.
|
|
316
|
-
window.
|
|
329
|
+
if (window.__spectestFontInliner) return;
|
|
330
|
+
window.__spectestFontInliner = true;
|
|
317
331
|
// Diagnostics ride the console-record plugin, so they land in the
|
|
318
332
|
// recording (and state.db) — our only debugging window into the
|
|
319
333
|
// headless page. Prefix is grep-able; keep them terse.
|
|
@@ -370,7 +384,12 @@ const RRWEB_BOOTSTRAP = `
|
|
|
370
384
|
}
|
|
371
385
|
}
|
|
372
386
|
}
|
|
373
|
-
|
|
387
|
+
// Every @font-face cssText this run already rewrote. A rule stays out
|
|
388
|
+
// of later scans, so an HMR update that adds one stylesheet costs one
|
|
389
|
+
// fetch, not a re-inline of the whole page.
|
|
390
|
+
var inlined = {};
|
|
391
|
+
var scans = 0, busy = false, rescan = false;
|
|
392
|
+
function collect() {
|
|
374
393
|
// Collect each @font-face's *cssText* (reliable for any CSSRule —
|
|
375
394
|
// unlike .style.setProperty('src',…), which silently no-ops on
|
|
376
395
|
// CSSFontFaceRule in Chrome) plus the http url()s inside it.
|
|
@@ -384,13 +403,26 @@ const RRWEB_BOOTSTRAP = `
|
|
|
384
403
|
eachFontFace(rules, function (rule) {
|
|
385
404
|
faceCount++;
|
|
386
405
|
var cssText = rule.cssText || "";
|
|
406
|
+
if (inlined[cssText]) return;
|
|
387
407
|
var urls = urlsIn(cssText, base);
|
|
388
408
|
if (urls.length) faces.push({ cssText: cssText, urls: urls });
|
|
389
409
|
});
|
|
390
410
|
}
|
|
391
|
-
|
|
392
|
-
|
|
411
|
+
// Log the first scan (so a page with no web fonts still says so) and
|
|
412
|
+
// every scan with work to do. A quiet re-trigger stays silent.
|
|
413
|
+
if (!scans++ || faces.length) {
|
|
414
|
+
log("sheets=" + sheets.length + " readable=" + readable +
|
|
415
|
+
" fontFaces=" + faceCount + " new=" + faces.length);
|
|
416
|
+
}
|
|
417
|
+
return faces;
|
|
418
|
+
}
|
|
419
|
+
function run() {
|
|
420
|
+
// One pass at a time. A trigger during a pass queues exactly one
|
|
421
|
+
// more, which then sees the marks the pass just wrote.
|
|
422
|
+
if (busy) { rescan = true; return; }
|
|
423
|
+
var faces = collect();
|
|
393
424
|
if (!faces.length) return;
|
|
425
|
+
busy = true;
|
|
394
426
|
var jobs = faces.map(function (face) {
|
|
395
427
|
return Promise.all(face.urls.map(function (u) {
|
|
396
428
|
return fetchDataUri(u.abs)
|
|
@@ -403,7 +435,9 @@ const RRWEB_BOOTSTRAP = `
|
|
|
403
435
|
text = text.split(pairs[k].token).join(pairs[k].dataUri);
|
|
404
436
|
changed = true;
|
|
405
437
|
}
|
|
406
|
-
|
|
438
|
+
if (!changed) return null;
|
|
439
|
+
inlined[face.cssText] = true;
|
|
440
|
+
return text;
|
|
407
441
|
});
|
|
408
442
|
});
|
|
409
443
|
Promise.all(jobs).then(function (texts) {
|
|
@@ -426,15 +460,21 @@ const RRWEB_BOOTSTRAP = `
|
|
|
426
460
|
log("took full snapshot");
|
|
427
461
|
}
|
|
428
462
|
} catch (e) { log("snapshot FAIL " + (e && e.message)); }
|
|
463
|
+
}).catch(function (e) {
|
|
464
|
+
log("run FAIL " + (e && e.message));
|
|
465
|
+
}).then(function () {
|
|
466
|
+
busy = false;
|
|
467
|
+
if (rescan) { rescan = false; setTimeout(run, 0); }
|
|
429
468
|
});
|
|
430
469
|
}
|
|
470
|
+
function schedule() { setTimeout(run, 0); }
|
|
431
471
|
try {
|
|
432
|
-
if (document.
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
472
|
+
if (document.readyState === "complete") schedule();
|
|
473
|
+
else window.addEventListener("load", schedule);
|
|
474
|
+
// Fires each time a batch of fonts finishes loading, including fonts
|
|
475
|
+
// pulled in by CSS that arrives after the load event.
|
|
476
|
+
if (document.fonts && document.fonts.addEventListener) {
|
|
477
|
+
document.fonts.addEventListener("loadingdone", schedule);
|
|
438
478
|
}
|
|
439
479
|
} catch (e) { log("init FAIL " + (e && e.message)); }
|
|
440
480
|
})();
|