@juxtapose/core 0.9.0 → 0.10.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/agent/handoff.d.ts +3 -1
- package/dist/agent/handoff.js +17 -0
- package/dist/agent/handoff.js.map +1 -1
- package/dist/browser/page.d.ts +9 -1
- package/dist/browser/page.js +7 -0
- package/dist/browser/page.js.map +1 -1
- package/dist/capture/capture.d.ts +7 -0
- package/dist/capture/capture.js +40 -8
- package/dist/capture/capture.js.map +1 -1
- package/dist/capture/config-errors.d.ts +10 -0
- package/dist/capture/config-errors.js +20 -0
- package/dist/capture/config-errors.js.map +1 -0
- package/dist/capture/idle.d.ts +88 -0
- package/dist/capture/idle.js +545 -0
- package/dist/capture/idle.js.map +1 -0
- package/dist/capture/pool.d.ts +6 -0
- package/dist/capture/pool.js +1 -0
- package/dist/capture/pool.js.map +1 -1
- package/dist/capture/settle-options.d.ts +78 -0
- package/dist/capture/settle-options.js +234 -0
- package/dist/capture/settle-options.js.map +1 -0
- package/dist/capture/settle.d.ts +0 -18
- package/dist/capture/settle.js +7 -100
- package/dist/capture/settle.js.map +1 -1
- package/dist/capture/snap.d.ts +3 -0
- package/dist/capture/snap.js +7 -1
- package/dist/capture/snap.js.map +1 -1
- package/dist/capture/variants.d.ts +1 -4
- package/dist/capture/variants.js +22 -10
- package/dist/capture/variants.js.map +1 -1
- package/dist/diff/structural.d.ts +4 -1
- package/dist/diff/structural.js +3 -0
- package/dist/diff/structural.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/run/run.d.ts +4 -0
- package/dist/run/run.js +17 -0
- package/dist/run/run.js.map +1 -1
- package/dist/types.d.ts +60 -1
- package/package.json +1 -1
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
// Event-driven settle: wait as long as the page still has work, not a fixed
|
|
2
|
+
// quiet window.
|
|
3
|
+
//
|
|
4
|
+
// Replaces the 150 ms DOM-quiet window (capped at 500 ms) that ran on every
|
|
5
|
+
// story. Measured in the settle spike (raw CDP replica of this pipeline, 5
|
|
6
|
+
// runs per story, chrome-headless-shell 151.0.7922.34): byte-identical to the
|
|
7
|
+
// quiet window on 29/29 example stories (Storybook 15, Ladle 14), stable 5/5,
|
|
8
|
+
// settle p50 168 -> 39 ms (Storybook) and 162 -> 34 ms (Ladle). On adversarial
|
|
9
|
+
// pages it captures the final state of setTimeout(300) and (800) and of a
|
|
10
|
+
// fetch resolving after 200 ms, all of which the quiet window captured
|
|
11
|
+
// mid-update (0/5), and it does not hang on a lazy image below the fold,
|
|
12
|
+
// where the old uncapped image wait in `drain` never returned.
|
|
13
|
+
//
|
|
14
|
+
// Shipped, through the CLI (2026-10-13, Apple M5 Pro, 15 cores, load average
|
|
15
|
+
// 15-18, median of 5, interleaved with main): `jux run --all` on the
|
|
16
|
+
// Storybook example 1339 -> 653 ms (story p50 203 -> 75 ms), Ladle 1127 ->
|
|
17
|
+
// 603 ms (208 -> 80 ms); a warm `jux snap` of one story 356 -> 209 ms. Every
|
|
18
|
+
// default and variant capture (Storybook 18, Ladle 16) byte-identical to
|
|
19
|
+
// baselines approved by the quiet-window build, fresh launch and daemon.
|
|
20
|
+
//
|
|
21
|
+
// Two halves. An init script, installed before any page script runs, counts
|
|
22
|
+
// the page's own pending work: short timers, animation frames, posted
|
|
23
|
+
// messages, DOM mutations, loading fonts and loading in-viewport images. CDP
|
|
24
|
+
// Network events count in-flight requests, which the page cannot see for
|
|
25
|
+
// itself (a fetch started before any wrapper could be installed, a <link>
|
|
26
|
+
// stylesheet, an image the parser started). Idle is both at zero, re-checked
|
|
27
|
+
// once more after a round trip because renderer and browser events are not
|
|
28
|
+
// ordered against each other.
|
|
29
|
+
//
|
|
30
|
+
// Never throws: a wait that hits its cap is reported, and the page is captured
|
|
31
|
+
// as it is. A slow story must produce a reviewable result, not abort a run.
|
|
32
|
+
import { SendTimeoutError } from '../browser/cdp.js';
|
|
33
|
+
import { matchPattern } from './settle-options.js';
|
|
34
|
+
/**
|
|
35
|
+
* Runs before any page script (Page.addScriptToEvaluateOnNewDocument), so the
|
|
36
|
+
* wrappers are in place before a framework captures the natives. A library
|
|
37
|
+
* that re-patches them later (zone.js, Sentry) is still tracked as long as it
|
|
38
|
+
* calls through, which they do.
|
|
39
|
+
*
|
|
40
|
+
* String timer handlers pass straight through, untracked: wrapping them would
|
|
41
|
+
* need eval, which a page's CSP may forbid.
|
|
42
|
+
*/
|
|
43
|
+
const IDLE_INIT = `(function () {
|
|
44
|
+
if (window.__juxIdle) return;
|
|
45
|
+
var W = window;
|
|
46
|
+
var S = { timers: new Map(), rafs: new Set(), sent: 0, delivered: 0, workers: new Map(), mut: 0, ready: false };
|
|
47
|
+
var oST = W.setTimeout, oCT = W.clearTimeout, oSI = W.setInterval, oCI = W.clearInterval;
|
|
48
|
+
var oRAF = W.requestAnimationFrame, oCAF = W.cancelAnimationFrame, oPM = W.postMessage;
|
|
49
|
+
var PP = MessagePort.prototype, oPPM = PP.postMessage, oAEL = PP.addEventListener, oREL = PP.removeEventListener;
|
|
50
|
+
|
|
51
|
+
// Task hop on a private channel, created before MessagePort is patched so
|
|
52
|
+
// its own messages are never counted as the page's.
|
|
53
|
+
var hop = (function () { var ch = new MessageChannel(); var q = [];
|
|
54
|
+
ch.port1.onmessage = function () { var f = q.shift(); if (f) f(); };
|
|
55
|
+
return function (f) { q.push(f); oPPM.call(ch.port2, 0); }; })();
|
|
56
|
+
|
|
57
|
+
// Polls and clocks: a paced timer (delay >= 16 ms, a frame) re-armed from
|
|
58
|
+
// the same call site after an earlier one there fired counts only if the
|
|
59
|
+
// DOM changed since that fire. A poll that changes nothing (same function,
|
|
60
|
+
// fresh closure or arrow) stops counting after its first period; a chain
|
|
61
|
+
// that reveals something each step (retry with backoff, a typewriter, a
|
|
62
|
+
// staged reveal) is waited out. The site is the whole stack minus this
|
|
63
|
+
// wrapper, not the top frame, so a shared sleep() helper is a different site
|
|
64
|
+
// per caller. Mutations are flushed with takeRecords() so a re-arm sees the
|
|
65
|
+
// changes its own callback just made.
|
|
66
|
+
//
|
|
67
|
+
// Measured in the review's prototype (round 2): closure, arrow and
|
|
68
|
+
// same-function 200 ms polls settle in 440-453 ms unflagged (they pinned the
|
|
69
|
+
// 1500 ms cap before); a 3-step 100 ms self-chain, sleep() chains,
|
|
70
|
+
// timer-1200-chain, timeout-chain and the timeout-50/120/300/800 pages all
|
|
71
|
+
// capture their final state 3/3. A clock that repaints every tick still
|
|
72
|
+
// counts and hits the cap, flagged: it needs a mask either way. Faster
|
|
73
|
+
// re-arms (setTimeout(step, 0) chunked work) are never keyed and always count.
|
|
74
|
+
var PACED_MS = 16, sites = new Map(), MO = null;
|
|
75
|
+
var flushMut = function () { if (MO) S.mut += MO.takeRecords().length; };
|
|
76
|
+
W.setTimeout = function (fn, delay) {
|
|
77
|
+
if (typeof fn !== 'function') return oST.apply(W, arguments);
|
|
78
|
+
var args = Array.prototype.slice.call(arguments, 2); var d = Math.max(0, Number(delay) || 0); var id;
|
|
79
|
+
var key = null, counted = true;
|
|
80
|
+
if (d >= PACED_MS) {
|
|
81
|
+
key = (new Error().stack || '').split('\\n').slice(2).join('\\n');
|
|
82
|
+
var site = sites.get(key);
|
|
83
|
+
if (site && site.fired) { flushMut(); counted = S.mut !== site.mutAtFire; }
|
|
84
|
+
}
|
|
85
|
+
var cb = function () { S.timers.delete(id);
|
|
86
|
+
if (key !== null) { flushMut(); sites.set(key, { fired: true, mutAtFire: S.mut }); }
|
|
87
|
+
return fn.apply(W, args); };
|
|
88
|
+
id = oST.call(W, cb, d);
|
|
89
|
+
if (key !== null && !sites.has(key)) sites.set(key, { fired: false });
|
|
90
|
+
if (counted) S.timers.set(id, d);
|
|
91
|
+
return id;
|
|
92
|
+
};
|
|
93
|
+
W.clearTimeout = function (id) { S.timers.delete(id); return oCT.call(W, id); };
|
|
94
|
+
// An interval counts until its first tick only: it must not block forever.
|
|
95
|
+
W.setInterval = function (fn, delay) {
|
|
96
|
+
if (typeof fn !== 'function') return oSI.apply(W, arguments);
|
|
97
|
+
var args = Array.prototype.slice.call(arguments, 2); var d = Math.max(0, Number(delay) || 0); var id; var first = true;
|
|
98
|
+
var cb = function () { if (first) { first = false; S.timers.delete(id); } return fn.apply(W, args); };
|
|
99
|
+
id = oSI.call(W, cb, d); S.timers.set(id, d); return id;
|
|
100
|
+
};
|
|
101
|
+
W.clearInterval = function (id) { S.timers.delete(id); return oCI.call(W, id); };
|
|
102
|
+
// rAF re-armed from inside a rAF callback is an animation loop; stop counting
|
|
103
|
+
// after 3 generations or a canvas animation pins the wait at the cap
|
|
104
|
+
// (measured: a perpetual rAF loop settles in 35-40 ms with this).
|
|
105
|
+
var rafGen = 0;
|
|
106
|
+
W.requestAnimationFrame = function (fn) {
|
|
107
|
+
var gen = rafGen;
|
|
108
|
+
var id = oRAF.call(W, function (t) { S.rafs.delete(id); rafGen = gen + 1; try { return fn(t); } finally { rafGen = 0; } });
|
|
109
|
+
if (gen < 3) S.rafs.add(id); return id;
|
|
110
|
+
};
|
|
111
|
+
W.cancelAnimationFrame = function (id) { S.rafs.delete(id); return oCAF.call(W, id); };
|
|
112
|
+
// Posted messages (React's scheduler uses a MessageChannel): count sends
|
|
113
|
+
// and deliveries, each event once however many listeners see it. Pending
|
|
114
|
+
// is the difference; the waiter treats it as stale only when deliveries
|
|
115
|
+
// stop moving (a port nobody listens to), never while they continue (the
|
|
116
|
+
// review measured 40 x 5 ms of scheduler slices captured mid-render when
|
|
117
|
+
// a steady 1-in-flight count was read as stale).
|
|
118
|
+
var seen = new WeakSet();
|
|
119
|
+
var deliver = function (e) { if (e && typeof e === 'object') { if (seen.has(e)) return; seen.add(e); }
|
|
120
|
+
if (S.delivered < S.sent) S.delivered++; };
|
|
121
|
+
W.postMessage = function () { S.sent++; return oPM.apply(W, arguments); };
|
|
122
|
+
W.addEventListener('message', deliver, true);
|
|
123
|
+
var wrapped = new WeakMap();
|
|
124
|
+
var wrap = function (fn) { if (typeof fn !== 'function') return fn; var w = wrapped.get(fn);
|
|
125
|
+
if (!w) { w = function (e) { deliver(e); return fn.call(this, e); }; wrapped.set(fn, w); } return w; };
|
|
126
|
+
PP.postMessage = function () { S.sent++; return oPPM.apply(this, arguments); };
|
|
127
|
+
PP.addEventListener = function (type, fn, opt) { return oAEL.call(this, type, type === 'message' ? wrap(fn) : fn, opt); };
|
|
128
|
+
PP.removeEventListener = function (type, fn, opt) {
|
|
129
|
+
return oREL.call(this, type, type === 'message' && typeof fn === 'function' ? (wrapped.get(fn) || fn) : fn, opt); };
|
|
130
|
+
var onmsg = Object.getOwnPropertyDescriptor(PP, 'onmessage');
|
|
131
|
+
Object.defineProperty(PP, 'onmessage', { configurable: true,
|
|
132
|
+
get: function () { return onmsg.get.call(this); }, set: function (fn) { return onmsg.set.call(this, wrap(fn)); } });
|
|
133
|
+
|
|
134
|
+
// A dedicated Worker runs where this script can't see; its script request
|
|
135
|
+
// never completes on the page's session either. What is countable is the
|
|
136
|
+
// conversation: a message posted to the worker is pending until a message
|
|
137
|
+
// comes back, within the timer horizon of the post; and a new worker gets a
|
|
138
|
+
// 300 ms startup grace for unsolicited work, ended by its first message,
|
|
139
|
+
// error or terminate(). A silent worker (comlink-style, answering only when
|
|
140
|
+
// asked) cost ~1040 ms per capture when the whole horizon applied
|
|
141
|
+
// (review round 2); with the grace it costs at most 300 ms, and the 80 ms and
|
|
142
|
+
// 120 ms startup probes (worker-80, worker-delay) still capture their
|
|
143
|
+
// answer. Reflect.construct keeps "class X extends Worker" working.
|
|
144
|
+
var OW = W.Worker, wid = 0, STARTUP_MS = 300;
|
|
145
|
+
if (typeof OW === 'function') {
|
|
146
|
+
var JW = function Worker(url, opts) {
|
|
147
|
+
var w = Reflect.construct(OW, Array.prototype.slice.call(arguments), new.target || OW);
|
|
148
|
+
var id = ++wid; var rec = { t: performance.now(), src: String(url), started: true, posted: 0, replies: 0, lastPost: 0 };
|
|
149
|
+
rec.id = id; S.workers.set(id, rec); recs.set(w, rec);
|
|
150
|
+
w.addEventListener('message', function () { rec.started = false; if (rec.replies < rec.posted) rec.replies++; });
|
|
151
|
+
w.addEventListener('error', function () { rec.started = false; rec.replies = rec.posted; });
|
|
152
|
+
return w;
|
|
153
|
+
};
|
|
154
|
+
// On the prototype, not the instance, so a subclass's own overrides win.
|
|
155
|
+
var recs = new WeakMap(), WP = OW.prototype, oWPM = WP.postMessage, oWT = WP.terminate;
|
|
156
|
+
WP.postMessage = function () { var r = recs.get(this); if (r) { r.posted++; r.lastPost = performance.now(); } return oWPM.apply(this, arguments); };
|
|
157
|
+
WP.terminate = function () { var r = recs.get(this); if (r) S.workers.delete(r.id); return oWT.apply(this, arguments); };
|
|
158
|
+
JW.prototype = WP;
|
|
159
|
+
Object.setPrototypeOf(JW, OW);
|
|
160
|
+
W.Worker = JW;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
MO = new MutationObserver(function (list) { S.mut += list.length; });
|
|
164
|
+
MO.observe(document, { childList: true, subtree: true, attributes: true, characterData: true });
|
|
165
|
+
|
|
166
|
+
// The page's half of settle.ready. Always defined under jux, so a page can
|
|
167
|
+
// call it unconditionally (window.__juxtapose?.ready() outside jux).
|
|
168
|
+
W.__juxtapose = { ready: function () { S.ready = true; } };
|
|
169
|
+
|
|
170
|
+
var pendingImages = function () {
|
|
171
|
+
var vh = W.innerHeight, vw = W.innerWidth, out = [];
|
|
172
|
+
Array.prototype.forEach.call(document.images, function (img) {
|
|
173
|
+
if (img.complete) return;
|
|
174
|
+
// A lazy image outside the viewport, or not rendered at all
|
|
175
|
+
// (display: none), never loads; waiting for it is what hung the old drain.
|
|
176
|
+
if (img.loading === 'lazy') { if (img.getClientRects().length === 0) return;
|
|
177
|
+
var r = img.getBoundingClientRect(); if (r.bottom < 0 || r.top > vh || r.right < 0 || r.left > vw) return; }
|
|
178
|
+
out.push(img.currentSrc || img.src || '(no src)');
|
|
179
|
+
});
|
|
180
|
+
return out;
|
|
181
|
+
};
|
|
182
|
+
var snapshot = function (horizon) {
|
|
183
|
+
var timers = 0; S.timers.forEach(function (d) { if (d <= horizon) timers++; });
|
|
184
|
+
var now = performance.now(), workers = [];
|
|
185
|
+
S.workers.forEach(function (w) {
|
|
186
|
+
if ((w.started && now - w.t <= STARTUP_MS) || (w.replies < w.posted && now - w.lastPost <= horizon)) workers.push(w.src); });
|
|
187
|
+
var imgs = pendingImages();
|
|
188
|
+
return { timers: timers, rafs: S.rafs.size, msgs: S.sent - S.delivered, delivered: S.delivered, mut: S.mut,
|
|
189
|
+
fonts: document.fonts.status, images: imgs.length, imageSrcs: imgs.slice(0, 3),
|
|
190
|
+
workers: workers.length, workerSrcs: workers.slice(0, 3), ready: S.ready };
|
|
191
|
+
};
|
|
192
|
+
W.__juxIdle = { snapshot: snapshot, reset: function () { S.ready = false; } };
|
|
193
|
+
|
|
194
|
+
// Resolves 'idle' when two consecutive task hops each see no pending work
|
|
195
|
+
// and no mutation since the previous hop, or 'cap' at capMs.
|
|
196
|
+
W.__juxIdleWait = function (capMs, horizon, needReady) {
|
|
197
|
+
return new Promise(function (resolve) {
|
|
198
|
+
var t0 = performance.now(); var lastMut = -1; var lastDelivered = -1; var quiet = 0; var stale = 0; var done = false; var changing = false;
|
|
199
|
+
var finish = function (status, s) { if (done) return; done = true; oCT.call(W, capTimer);
|
|
200
|
+
s = s || snapshot(horizon); s.changing = changing;
|
|
201
|
+
resolve({ status: status, waitedMs: performance.now() - t0, snap: s }); };
|
|
202
|
+
var capTimer = oST.call(W, function () { finish('cap'); }, capMs);
|
|
203
|
+
var check = function () {
|
|
204
|
+
if (done) return;
|
|
205
|
+
var s = snapshot(horizon);
|
|
206
|
+
if (s.msgs > 0 && s.delivered === lastDelivered) stale++; else stale = 0; lastDelivered = s.delivered;
|
|
207
|
+
var msgsOk = s.msgs === 0 || stale >= 3;
|
|
208
|
+
var noWork = s.timers === 0 && s.rafs === 0 && msgsOk && s.workers === 0 && s.fonts !== 'loading' && s.images === 0 && (!needReady || s.ready);
|
|
209
|
+
changing = s.mut !== lastMut && lastMut !== -1;
|
|
210
|
+
var isQuiet = noWork && s.mut === lastMut;
|
|
211
|
+
lastMut = s.mut;
|
|
212
|
+
quiet = isQuiet ? quiet + 1 : 0;
|
|
213
|
+
if (quiet >= 2) return finish('idle', s);
|
|
214
|
+
if (noWork) hop(check); // a mutation just happened: look again next task
|
|
215
|
+
else if (s.rafs > 0) oRAF.call(W, function () { hop(check); }); // sleep to the frame edge
|
|
216
|
+
else oST.call(W, check, 4); // timer/font/image/worker/ready pending: poll cheaply
|
|
217
|
+
};
|
|
218
|
+
// First check after a frame: style and layout must run once before
|
|
219
|
+
// fonts and in-viewport images start loading.
|
|
220
|
+
oRAF.call(W, function () { hop(check); });
|
|
221
|
+
});
|
|
222
|
+
};
|
|
223
|
+
})();`;
|
|
224
|
+
/** Completed requests kept per document for `require`; past this a page is
|
|
225
|
+
* a firehose and the oldest are dropped. */
|
|
226
|
+
const MAX_DONE = 5000;
|
|
227
|
+
/** In-flight and completed requests on one page, from CDP Network events. */
|
|
228
|
+
export class NetworkTracker {
|
|
229
|
+
inflight = new Map();
|
|
230
|
+
done = [];
|
|
231
|
+
listeners = new Set();
|
|
232
|
+
/** In flight when the current story started on a warm switch: the last
|
|
233
|
+
* story's, never this one's. */
|
|
234
|
+
excluded = new Set();
|
|
235
|
+
/** The committed main document's loader. */
|
|
236
|
+
mainLoader;
|
|
237
|
+
constructor(page, mainFrameId) {
|
|
238
|
+
page.on('Network.requestWillBeSent', (p) => {
|
|
239
|
+
// A dedicated Worker's script request has no loader and never gets
|
|
240
|
+
// loadingFinished on this session (review: every capture of a page
|
|
241
|
+
// with `new Worker('/w.js')` pinned at the cap). The init script counts
|
|
242
|
+
// the worker's conversation instead.
|
|
243
|
+
if (p.loaderId === '')
|
|
244
|
+
return;
|
|
245
|
+
this.inflight.set(p.requestId, {
|
|
246
|
+
url: p.request.url,
|
|
247
|
+
...(p.type !== undefined ? { type: p.type } : {}),
|
|
248
|
+
...(p.frameId === mainFrameId ? { mainLoader: p.loaderId } : {}),
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
// The new main document commits. Its predecessor's requests, including
|
|
252
|
+
// ones it started between the navigation's start and this commit, never
|
|
253
|
+
// get loadingFailed (spike: a long poll pinned the next page at the cap;
|
|
254
|
+
// review: a 2 ms poller flagged the following static page 4 of 6
|
|
255
|
+
// times), and its completions must not satisfy this one's `require`.
|
|
256
|
+
// On the commit, not on the Document request: a navigation that never
|
|
257
|
+
// commits (a 204, a download) must leave the live document's requests
|
|
258
|
+
// counted (review round 2). A request is kept by its loader, not dropped
|
|
259
|
+
// on arrival, because Network events and the commit come from different
|
|
260
|
+
// processes and a new document's first fetch can be reported before it.
|
|
261
|
+
page.on('Page.frameNavigated', ({ frame }) => {
|
|
262
|
+
if (frame.parentId !== undefined || frame.id !== mainFrameId)
|
|
263
|
+
return;
|
|
264
|
+
this.mainLoader = frame.loaderId;
|
|
265
|
+
for (const [id, r] of this.inflight)
|
|
266
|
+
if (r.mainLoader !== undefined && r.mainLoader !== frame.loaderId) {
|
|
267
|
+
this.inflight.delete(id);
|
|
268
|
+
this.excluded.delete(id);
|
|
269
|
+
}
|
|
270
|
+
this.done = [];
|
|
271
|
+
this.excluded.clear();
|
|
272
|
+
for (const l of [...this.listeners])
|
|
273
|
+
l();
|
|
274
|
+
});
|
|
275
|
+
const finish = (p) => {
|
|
276
|
+
const r = this.inflight.get(p.requestId);
|
|
277
|
+
if (!r)
|
|
278
|
+
return;
|
|
279
|
+
this.inflight.delete(p.requestId);
|
|
280
|
+
this.excluded.delete(p.requestId);
|
|
281
|
+
this.done.push(r);
|
|
282
|
+
if (this.done.length > MAX_DONE)
|
|
283
|
+
this.done.splice(0, this.done.length - MAX_DONE);
|
|
284
|
+
for (const l of [...this.listeners])
|
|
285
|
+
l();
|
|
286
|
+
};
|
|
287
|
+
page.on('Network.loadingFinished', finish);
|
|
288
|
+
page.on('Network.loadingFailed', finish);
|
|
289
|
+
}
|
|
290
|
+
/** A warm switch renders a new story in the same document: the last
|
|
291
|
+
* story's completions must not satisfy `require`, and its requests still
|
|
292
|
+
* in flight (a long poll) must not pin this one at the cap. */
|
|
293
|
+
reset() {
|
|
294
|
+
this.done = [];
|
|
295
|
+
this.excluded = new Set(this.inflight.keys());
|
|
296
|
+
}
|
|
297
|
+
/** In-flight requests the wait counts: required, or not ignored. */
|
|
298
|
+
counted(s) {
|
|
299
|
+
return [...this.inflight.entries()]
|
|
300
|
+
.filter(([id, r]) => !this.excluded.has(id) &&
|
|
301
|
+
// Another main-frame loader: the previous document's, or a
|
|
302
|
+
// navigation that has not committed (or never will).
|
|
303
|
+
(r.mainLoader === undefined ||
|
|
304
|
+
this.mainLoader === undefined ||
|
|
305
|
+
r.mainLoader === this.mainLoader))
|
|
306
|
+
.map(([, r]) => r)
|
|
307
|
+
.filter((r) => s.require.some((p) => matchPattern(p, r.url, r.type)) ||
|
|
308
|
+
!s.ignore.some((p) => matchPattern(p, r.url, r.type)));
|
|
309
|
+
}
|
|
310
|
+
/** `require` patterns no completed request has matched yet. */
|
|
311
|
+
missing(s) {
|
|
312
|
+
return s.require
|
|
313
|
+
.filter((p) => !this.done.some((r) => matchPattern(p, r.url, r.type)))
|
|
314
|
+
.map((p) => p.source);
|
|
315
|
+
}
|
|
316
|
+
busy(s) {
|
|
317
|
+
return this.counted(s).length > 0 || this.missing(s).length > 0;
|
|
318
|
+
}
|
|
319
|
+
/** Resolves when the wait no longer counts anything, or after `ms`. */
|
|
320
|
+
async settled(s, ms) {
|
|
321
|
+
if (!this.busy(s))
|
|
322
|
+
return;
|
|
323
|
+
await new Promise((resolve) => {
|
|
324
|
+
const done = () => {
|
|
325
|
+
clearTimeout(timer);
|
|
326
|
+
this.listeners.delete(check);
|
|
327
|
+
resolve();
|
|
328
|
+
};
|
|
329
|
+
const check = () => {
|
|
330
|
+
if (!this.busy(s))
|
|
331
|
+
done();
|
|
332
|
+
};
|
|
333
|
+
const timer = setTimeout(done, Math.max(0, ms));
|
|
334
|
+
this.listeners.add(check);
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
const installed = new WeakMap();
|
|
339
|
+
/**
|
|
340
|
+
* Install the init script and the request tracker, once per page, before
|
|
341
|
+
* its first navigation: the script applies to every later document on the
|
|
342
|
+
* page. Network.enable is already part of page init.
|
|
343
|
+
*/
|
|
344
|
+
export function installIdleDetector(page) {
|
|
345
|
+
let p = installed.get(page);
|
|
346
|
+
if (!p) {
|
|
347
|
+
p = (async () => {
|
|
348
|
+
await page
|
|
349
|
+
.send('Page.addScriptToEvaluateOnNewDocument', { source: IDLE_INIT })
|
|
350
|
+
.catch(() => { });
|
|
351
|
+
if (!page.on)
|
|
352
|
+
return { net: null };
|
|
353
|
+
const tree = await page.send('Page.getFrameTree').catch(() => undefined);
|
|
354
|
+
const mainFrameId = tree?.frameTree?.frame?.id;
|
|
355
|
+
return {
|
|
356
|
+
net: new NetworkTracker(page, mainFrameId),
|
|
357
|
+
};
|
|
358
|
+
})();
|
|
359
|
+
installed.set(page, p);
|
|
360
|
+
}
|
|
361
|
+
return p;
|
|
362
|
+
}
|
|
363
|
+
/** Before a story renders: forget the last story's completions, and on a
|
|
364
|
+
* warm switch (same document) its ready() call. */
|
|
365
|
+
export async function resetIdle(page, idle, warm) {
|
|
366
|
+
idle.net?.reset();
|
|
367
|
+
if (warm)
|
|
368
|
+
await page.evaluate('window.__juxIdle && window.__juxIdle.reset()').catch(() => { });
|
|
369
|
+
}
|
|
370
|
+
const now = () => performance.now();
|
|
371
|
+
const isSnapshot = (v) => typeof v === 'object' && v !== null && typeof v.mut === 'number';
|
|
372
|
+
/**
|
|
373
|
+
* Wait until the page reports no pending work and no counted request is in
|
|
374
|
+
* flight, or `capMs` passes. Never throws.
|
|
375
|
+
*/
|
|
376
|
+
export async function waitForIdle(page, idle, s, capMs = s.timeoutMs) {
|
|
377
|
+
const t0 = now();
|
|
378
|
+
let snap;
|
|
379
|
+
const timeout = () => ({
|
|
380
|
+
status: 'timeout',
|
|
381
|
+
waitedMs: now() - t0,
|
|
382
|
+
...(snap ? { snap } : {}),
|
|
383
|
+
pending: describePending(snap, idle.net, s),
|
|
384
|
+
});
|
|
385
|
+
for (;;) {
|
|
386
|
+
const remaining = capMs - (now() - t0);
|
|
387
|
+
if (remaining <= 0)
|
|
388
|
+
return timeout();
|
|
389
|
+
let r;
|
|
390
|
+
try {
|
|
391
|
+
r = await page.evaluate(`window.__juxIdleWait ? window.__juxIdleWait(${Math.ceil(remaining)}, ${s.horizonMs}, ${s.ready}) : Promise.resolve({ status: 'noinit' })`, undefined,
|
|
392
|
+
// The in-page cap fires first; this only matters if the page is wedged.
|
|
393
|
+
{ timeout: Math.ceil(remaining) + 2000 });
|
|
394
|
+
}
|
|
395
|
+
catch (err) {
|
|
396
|
+
// A wedged page (a synchronous loop) would only wedge a second evaluate
|
|
397
|
+
// too: worst case cap + 2 s + 2 s (review round 2). Skip straight to the
|
|
398
|
+
// capture; a navigation mid-wait gets the fallback wait.
|
|
399
|
+
if (err instanceof SendTimeoutError)
|
|
400
|
+
return {
|
|
401
|
+
status: 'fallback',
|
|
402
|
+
waitedMs: now() - t0,
|
|
403
|
+
pending: [
|
|
404
|
+
'the page stopped answering during the wait; captured without waiting',
|
|
405
|
+
],
|
|
406
|
+
};
|
|
407
|
+
return fallback(page, t0, capMs, 'the page navigated during the wait');
|
|
408
|
+
}
|
|
409
|
+
const status = typeof r === 'object' && r !== null
|
|
410
|
+
? r.status
|
|
411
|
+
: undefined;
|
|
412
|
+
const got = r?.snap;
|
|
413
|
+
if (isSnapshot(got))
|
|
414
|
+
snap = got;
|
|
415
|
+
if (status === 'cap')
|
|
416
|
+
return timeout();
|
|
417
|
+
if (status !== 'idle')
|
|
418
|
+
return fallback(page, t0, capMs, 'the idle detector was not installed in this page');
|
|
419
|
+
const net = idle.net;
|
|
420
|
+
if (!net)
|
|
421
|
+
return { status: 'idle', waitedMs: now() - t0, ...(snap ? { snap } : {}) };
|
|
422
|
+
if (net.busy(s)) {
|
|
423
|
+
await net.settled(s, capMs - (now() - t0));
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
// One more round trip, so the Network event for a request the page
|
|
427
|
+
// started just before it reported idle has arrived.
|
|
428
|
+
await page.evaluate('1').catch(() => { });
|
|
429
|
+
if (net.busy(s)) {
|
|
430
|
+
await net.settled(s, capMs - (now() - t0));
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
433
|
+
return { status: 'idle', waitedMs: now() - t0, ...(snap ? { snap } : {}) };
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* When the detector can't run, wait the way the quiet window did: fonts,
|
|
438
|
+
* eager images and 100 ms without a DOM change, all inside what is left of the
|
|
439
|
+
* cap. Flagged `settle-fallback`, so the weaker wait is never silent.
|
|
440
|
+
*/
|
|
441
|
+
async function fallback(page, t0, capMs, why) {
|
|
442
|
+
const remaining = Math.max(0, Math.ceil(capMs - (now() - t0)));
|
|
443
|
+
await page
|
|
444
|
+
.evaluate(`new Promise(function (resolve) {
|
|
445
|
+
var cap = setTimeout(resolve, ${remaining});
|
|
446
|
+
Promise.resolve(document.fonts && document.fonts.ready).then(function () {
|
|
447
|
+
return Promise.all(Array.prototype.filter.call(document.images, function (i) { return !i.complete && i.loading !== 'lazy'; })
|
|
448
|
+
.map(function (i) { return new Promise(function (r) { i.addEventListener('load', r, { once: true }); i.addEventListener('error', r, { once: true }); }); }));
|
|
449
|
+
}).then(function () {
|
|
450
|
+
var t; var fin = function () { o.disconnect(); clearTimeout(cap); resolve(); };
|
|
451
|
+
var o = new MutationObserver(function () { clearTimeout(t); t = setTimeout(fin, 100); });
|
|
452
|
+
o.observe(document, { childList: true, subtree: true, attributes: true, characterData: true });
|
|
453
|
+
t = setTimeout(fin, 100);
|
|
454
|
+
});
|
|
455
|
+
})`, undefined, { timeout: remaining + 2000 })
|
|
456
|
+
.catch(() => { });
|
|
457
|
+
return {
|
|
458
|
+
status: 'fallback',
|
|
459
|
+
waitedMs: now() - t0,
|
|
460
|
+
pending: [`${why}; waited for fonts, images and a quiet DOM only`],
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
/** After the paint barrier: did the DOM, fonts, images or network move? */
|
|
464
|
+
export async function movedSincePaint(page, idle, before, s) {
|
|
465
|
+
if (!before)
|
|
466
|
+
return false;
|
|
467
|
+
const after = await page
|
|
468
|
+
.evaluate(`window.__juxIdle ? window.__juxIdle.snapshot(${s.horizonMs}) : null`)
|
|
469
|
+
.catch(() => null);
|
|
470
|
+
if (!isSnapshot(after))
|
|
471
|
+
return false;
|
|
472
|
+
// Timers and messages too: a callback inside the barrier can schedule work
|
|
473
|
+
// without touching the DOM yet.
|
|
474
|
+
return (after.mut !== before.mut ||
|
|
475
|
+
after.timers > 0 ||
|
|
476
|
+
after.msgs > 0 ||
|
|
477
|
+
after.workers > 0 ||
|
|
478
|
+
after.fonts === 'loading' ||
|
|
479
|
+
after.images > 0 ||
|
|
480
|
+
idle.net?.busy(s) === true);
|
|
481
|
+
}
|
|
482
|
+
const MAX_REQUEST_LINES = 5;
|
|
483
|
+
/** A request URL as a person would name it: the path and query for http(s),
|
|
484
|
+
* else the URL, either one trimmed. */
|
|
485
|
+
function displayUrl(url) {
|
|
486
|
+
let out = url;
|
|
487
|
+
try {
|
|
488
|
+
const u = new URL(url);
|
|
489
|
+
if (u.protocol === 'http:' || u.protocol === 'https:')
|
|
490
|
+
out = u.pathname + u.search;
|
|
491
|
+
}
|
|
492
|
+
catch {
|
|
493
|
+
// not a URL; show it as is
|
|
494
|
+
}
|
|
495
|
+
return out.length > 100 ? `${out.slice(0, 99)}…` : out;
|
|
496
|
+
}
|
|
497
|
+
const plural = (n, one, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;
|
|
498
|
+
/**
|
|
499
|
+
* What was still pending at the cap, one line per kind, so an agent reading
|
|
500
|
+
* the result can respond: ignore a request, require one, raise the cap, or
|
|
501
|
+
* mask what keeps changing. Never empty.
|
|
502
|
+
*/
|
|
503
|
+
export function describePending(snap, net, s) {
|
|
504
|
+
const out = [];
|
|
505
|
+
if (net) {
|
|
506
|
+
const groups = new Map();
|
|
507
|
+
for (const r of net.counted(s)) {
|
|
508
|
+
const key = `${displayUrl(r.url)}\0${r.type ?? 'Other'}`;
|
|
509
|
+
groups.set(key, (groups.get(key) ?? 0) + 1);
|
|
510
|
+
}
|
|
511
|
+
const lines = [...groups.entries()]
|
|
512
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
513
|
+
.map(([key, n]) => {
|
|
514
|
+
const [url, type] = key.split('\0');
|
|
515
|
+
return `${plural(n, 'request')} to ${url} in flight (${type})`;
|
|
516
|
+
});
|
|
517
|
+
out.push(...lines.slice(0, MAX_REQUEST_LINES));
|
|
518
|
+
if (lines.length > MAX_REQUEST_LINES)
|
|
519
|
+
out.push(`${lines.length - MAX_REQUEST_LINES} more requests in flight`);
|
|
520
|
+
for (const p of net.missing(s))
|
|
521
|
+
out.push(`no request matching required pattern '${p}' has completed`);
|
|
522
|
+
}
|
|
523
|
+
if (snap) {
|
|
524
|
+
if (s.ready && !snap.ready)
|
|
525
|
+
out.push('window.__juxtapose.ready() was not called');
|
|
526
|
+
if (snap.timers > 0)
|
|
527
|
+
out.push(`${plural(snap.timers, 'timer')} due within ${s.horizonMs} ms`);
|
|
528
|
+
if (snap.rafs > 0)
|
|
529
|
+
out.push(`${plural(snap.rafs, 'animation frame callback')} pending`);
|
|
530
|
+
if (snap.msgs > 0)
|
|
531
|
+
out.push(`${plural(snap.msgs, 'posted message')} undelivered`);
|
|
532
|
+
if (snap.workers > 0)
|
|
533
|
+
out.push(`${plural(snap.workers, 'worker')} not answered yet: ${snap.workerSrcs.map(displayUrl).join(', ')}`);
|
|
534
|
+
if (snap.fonts === 'loading')
|
|
535
|
+
out.push('web fonts still loading');
|
|
536
|
+
if (snap.images > 0)
|
|
537
|
+
out.push(`${plural(snap.images, 'image')} still loading: ${snap.imageSrcs.map(displayUrl).join(', ')}`);
|
|
538
|
+
if (out.length === 0 && snap.changing)
|
|
539
|
+
out.push('the DOM kept changing');
|
|
540
|
+
}
|
|
541
|
+
if (out.length === 0)
|
|
542
|
+
out.push(`the page did not settle within ${s.timeoutMs} ms`);
|
|
543
|
+
return out;
|
|
544
|
+
}
|
|
545
|
+
//# sourceMappingURL=idle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idle.js","sourceRoot":"","sources":["../../src/capture/idle.ts"],"names":[],"mappings":"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"}
|
package/dist/capture/pool.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Browser } from '../browser/browser.js';
|
|
2
2
|
import type { Platform } from '../platform.js';
|
|
3
3
|
import type { Snapshot, StoryManifest, Viewport } from '../types.js';
|
|
4
|
+
import type { SettleLayer } from './settle-options.js';
|
|
4
5
|
/**
|
|
5
6
|
* Default parallelism.
|
|
6
7
|
*
|
|
@@ -25,6 +26,11 @@ export interface PoolOptions {
|
|
|
25
26
|
warmSwitch?: boolean;
|
|
26
27
|
/** Non-fatal notices from capture, e.g. an ignored live variant override. */
|
|
27
28
|
onWarning?: (message: string) => void;
|
|
29
|
+
/** Settle options around each story's own; see CaptureDeps. */
|
|
30
|
+
settleLayers?: {
|
|
31
|
+
project?: SettleLayer;
|
|
32
|
+
call?: SettleLayer;
|
|
33
|
+
};
|
|
28
34
|
}
|
|
29
35
|
export interface CaptureOutcome {
|
|
30
36
|
story: StoryManifest;
|
package/dist/capture/pool.js
CHANGED
|
@@ -63,6 +63,7 @@ export async function* capturePool(stories, opts) {
|
|
|
63
63
|
baseUrl: opts.baseUrl,
|
|
64
64
|
warmSwitch: opts.warmSwitch,
|
|
65
65
|
...(opts.onWarning ? { onWarning: opts.onWarning } : {}),
|
|
66
|
+
...(opts.settleLayers ? { settleLayers: opts.settleLayers } : {}),
|
|
66
67
|
};
|
|
67
68
|
try {
|
|
68
69
|
for (;;) {
|
package/dist/capture/pool.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pool.js","sourceRoot":"","sources":["../../src/capture/pool.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,6EAA6E;AAC7E,6CAA6C;AAE7C,OAAO,EACL,gBAAgB,GAGjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAa,MAAM,oBAAoB,CAAC;AAGjE,OAAO,EAAE,YAAY,EAAoB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"pool.js","sourceRoot":"","sources":["../../src/capture/pool.ts"],"names":[],"mappings":"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"}
|