why-hydration 0.1.3 → 0.1.5
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/CHANGELOG.md +81 -1
- package/LICENSE +21 -0
- package/README.md +597 -197
- package/dist/{chunk-NQX4TBV5.js → chunk-3I6F4K4L.js} +132 -48
- package/dist/chunk-3I6F4K4L.js.map +1 -0
- package/dist/{chunk-WQLUD25W.js → chunk-AS5DZZHI.js} +138 -53
- package/dist/chunk-AS5DZZHI.js.map +1 -0
- package/dist/{chunk-DSO337ME.cjs → chunk-AT6A77X3.cjs} +139 -54
- package/dist/chunk-AT6A77X3.cjs.map +1 -0
- package/dist/{chunk-OGQEPU7G.cjs → chunk-DXPTZB3Z.cjs} +44 -2
- package/dist/chunk-DXPTZB3Z.cjs.map +1 -0
- package/dist/{chunk-MTAU6G26.cjs → chunk-OFVFNPE6.cjs} +141 -57
- package/dist/chunk-OFVFNPE6.cjs.map +1 -0
- package/dist/{chunk-FV3PEJQE.js → chunk-XIM33ZGB.js} +44 -2
- package/dist/chunk-XIM33ZGB.js.map +1 -0
- package/dist/index.cjs +24 -24
- package/dist/index.d.cts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +2 -2
- package/dist/next/index.cjs +5 -5
- package/dist/next/index.js +3 -3
- package/dist/next/script.cjs +2 -2
- package/dist/next/script.js +1 -1
- package/dist/react.cjs +5 -5
- package/dist/react.js +3 -3
- package/package.json +4 -3
- package/dist/chunk-DSO337ME.cjs.map +0 -1
- package/dist/chunk-FV3PEJQE.js.map +0 -1
- package/dist/chunk-MTAU6G26.cjs.map +0 -1
- package/dist/chunk-NQX4TBV5.js.map +0 -1
- package/dist/chunk-OGQEPU7G.cjs.map +0 -1
- package/dist/chunk-WQLUD25W.js.map +0 -1
|
@@ -11,9 +11,17 @@ function readSnapshot() {
|
|
|
11
11
|
if (typeof window === "undefined") return void 0;
|
|
12
12
|
return window[SNAPSHOT_KEY];
|
|
13
13
|
}
|
|
14
|
+
var resolved = /* @__PURE__ */ new WeakMap();
|
|
14
15
|
function getServerHtmlForRoot(root) {
|
|
15
16
|
const snapshot = readSnapshot();
|
|
16
17
|
if (!snapshot) return void 0;
|
|
18
|
+
const cached = resolved.get(root);
|
|
19
|
+
if (cached && cached.snapshot === snapshot) return cached.html;
|
|
20
|
+
const html = resolveServerHtml(snapshot, root);
|
|
21
|
+
resolved.set(root, { snapshot, html });
|
|
22
|
+
return html;
|
|
23
|
+
}
|
|
24
|
+
function resolveServerHtml(snapshot, root) {
|
|
17
25
|
for (const selector of Object.keys(snapshot.roots)) {
|
|
18
26
|
try {
|
|
19
27
|
if (root.matches(selector) || root === document.querySelector(selector)) {
|
|
@@ -22,8 +30,42 @@ function getServerHtmlForRoot(root) {
|
|
|
22
30
|
} catch {
|
|
23
31
|
}
|
|
24
32
|
}
|
|
33
|
+
return findNestedServerHtml(snapshot, root);
|
|
34
|
+
}
|
|
35
|
+
function findNestedServerHtml(snapshot, root) {
|
|
36
|
+
if (!root.id) return void 0;
|
|
37
|
+
const idSelector = `#${escapeId(root.id)}`;
|
|
38
|
+
for (const selector of Object.keys(snapshot.roots)) {
|
|
39
|
+
let container = null;
|
|
40
|
+
try {
|
|
41
|
+
container = document.querySelector(selector);
|
|
42
|
+
} catch {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (!container || container === root || !container.contains(root)) continue;
|
|
46
|
+
const html = snapshot.roots[selector];
|
|
47
|
+
if (html == null) continue;
|
|
48
|
+
const parsed = parseInert(html, container.tagName);
|
|
49
|
+
let match = null;
|
|
50
|
+
try {
|
|
51
|
+
match = parsed.querySelector(idSelector);
|
|
52
|
+
} catch {
|
|
53
|
+
match = null;
|
|
54
|
+
}
|
|
55
|
+
if (match) return match.innerHTML;
|
|
56
|
+
}
|
|
25
57
|
return void 0;
|
|
26
58
|
}
|
|
59
|
+
function escapeId(id) {
|
|
60
|
+
const cssEscape = globalThis.CSS?.escape;
|
|
61
|
+
return typeof cssEscape === "function" ? cssEscape(id) : id.replace(/[^\w-]/g, "\\$&");
|
|
62
|
+
}
|
|
63
|
+
function parseInert(html, tagName) {
|
|
64
|
+
const doc = document.implementation.createHTMLDocument("");
|
|
65
|
+
const container = doc.createElement(tagName || "div");
|
|
66
|
+
container.innerHTML = html;
|
|
67
|
+
return container;
|
|
68
|
+
}
|
|
27
69
|
function captureSnapshotNow(selectors = DEFAULT_SNAPSHOT_SELECTORS) {
|
|
28
70
|
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
29
71
|
return void 0;
|
|
@@ -45,5 +87,5 @@ exports.captureSnapshotNow = captureSnapshotNow;
|
|
|
45
87
|
exports.getServerHtmlForRoot = getServerHtmlForRoot;
|
|
46
88
|
exports.getSnapshotScriptSource = getSnapshotScriptSource;
|
|
47
89
|
exports.readSnapshot = readSnapshot;
|
|
48
|
-
//# sourceMappingURL=chunk-
|
|
49
|
-
//# sourceMappingURL=chunk-
|
|
90
|
+
//# sourceMappingURL=chunk-DXPTZB3Z.cjs.map
|
|
91
|
+
//# sourceMappingURL=chunk-DXPTZB3Z.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/snapshot.ts"],"names":[],"mappings":"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","file":"chunk-DXPTZB3Z.cjs","sourcesContent":["export const DEFAULT_SNAPSHOT_SELECTORS = ['#root', '#__next', 'body'];\n\nexport const SNAPSHOT_KEY = '__WHY_HYDRATION_SNAPSHOT__';\n\nexport interface Snapshot {\n version: 1;\n capturedAt: number;\n roots: Record<string, string>;\n}\n\ndeclare global {\n interface Window {\n [SNAPSHOT_KEY]?: Snapshot;\n }\n}\n\nexport function getSnapshotScriptSource(\n selectors: readonly string[] = DEFAULT_SNAPSHOT_SELECTORS,\n): string {\n const serialized = JSON.stringify(selectors).replace(/</g, '\\\\u003c');\n return `(function(){var K=${JSON.stringify(SNAPSHOT_KEY)};if(typeof window===\"undefined\"||window[K])return;var S=${serialized};function cap(){if(window[K])return;var r={};for(var i=0;i<S.length;i++){var el=document.querySelector(S[i]);if(el)r[S[i]]=el.innerHTML;}window[K]={version:1,capturedAt:Date.now(),roots:r};}if(document.readyState!==\"loading\"){cap();}else{document.addEventListener(\"readystatechange\",function(){if(document.readyState===\"interactive\")cap();});document.addEventListener(\"DOMContentLoaded\",cap);}})();`;\n}\n\nexport function readSnapshot(): Snapshot | undefined {\n if (typeof window === 'undefined') return undefined;\n return window[SNAPSHOT_KEY];\n}\n\n/**\n * Resolving a root can require parsing the entire captured page (see\n * `findNestedServerHtml`), and the settling window asks the same question once\n * per pass. The snapshot is written once and never mutated, so the answer is\n * cached per root element and keyed on snapshot identity — a replaced snapshot\n * invalidates it. A WeakMap keeps detached roots collectable.\n */\nconst resolved = new WeakMap<\n Element,\n { snapshot: Snapshot; html: string | undefined }\n>();\n\nexport function getServerHtmlForRoot(root: Element): string | undefined {\n const snapshot = readSnapshot();\n if (!snapshot) return undefined;\n const cached = resolved.get(root);\n if (cached && cached.snapshot === snapshot) return cached.html;\n const html = resolveServerHtml(snapshot, root);\n resolved.set(root, { snapshot, html });\n return html;\n}\n\nfunction resolveServerHtml(\n snapshot: Snapshot,\n root: Element,\n): string | undefined {\n for (const selector of Object.keys(snapshot.roots)) {\n try {\n if (root.matches(selector) || root === document.querySelector(selector)) {\n return snapshot.roots[selector];\n }\n } catch {\n /* invalid selector */\n }\n }\n return findNestedServerHtml(snapshot, root);\n}\n\n/**\n * A root the caller asked for (`roots: ['#app']`) may sit *inside* a captured\n * root (`body`) instead of being one itself, because the snapshot selectors are\n * chosen on the server and the inspected roots on the client. Recover its\n * server HTML by locating the same element by id inside the captured markup, so\n * a custom `roots` option still works against the default snapshot selectors.\n */\nfunction findNestedServerHtml(\n snapshot: Snapshot,\n root: Element,\n): string | undefined {\n if (!root.id) return undefined;\n const idSelector = `#${escapeId(root.id)}`;\n for (const selector of Object.keys(snapshot.roots)) {\n let container: Element | null = null;\n try {\n container = document.querySelector(selector);\n } catch {\n continue; // invalid selector\n }\n if (!container || container === root || !container.contains(root)) continue;\n const html = snapshot.roots[selector];\n if (html == null) continue;\n const parsed = parseInert(html, container.tagName);\n let match: Element | null = null;\n try {\n match = parsed.querySelector(idSelector);\n } catch {\n match = null;\n }\n if (match) return match.innerHTML;\n }\n return undefined;\n}\n\nfunction escapeId(id: string): string {\n const cssEscape = (globalThis as { CSS?: { escape?(value: string): string } })\n .CSS?.escape;\n return typeof cssEscape === 'function'\n ? cssEscape(id)\n : id.replace(/[^\\w-]/g, '\\\\$&');\n}\n\n// Kept local rather than shared with the diff engine: this module is also\n// reached from the server-rendered `next/script` entry, which must not pull the\n// dev-only diff implementation into its bundle.\nfunction parseInert(html: string, tagName: string): Element {\n const doc = document.implementation.createHTMLDocument('');\n const container = doc.createElement(tagName || 'div');\n container.innerHTML = html;\n return container;\n}\n\nexport function captureSnapshotNow(\n selectors: readonly string[] = DEFAULT_SNAPSHOT_SELECTORS,\n): Snapshot | undefined {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return undefined;\n }\n if (window[SNAPSHOT_KEY]) return window[SNAPSHOT_KEY];\n const roots: Record<string, string> = {};\n for (const selector of selectors) {\n const el = document.querySelector(selector);\n if (el) roots[selector] = el.innerHTML;\n }\n const snapshot: Snapshot = { version: 1, capturedAt: Date.now(), roots };\n window[SNAPSHOT_KEY] = snapshot;\n return snapshot;\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
3
|
+
var chunkAT6A77X3_cjs = require('./chunk-AT6A77X3.cjs');
|
|
4
|
+
var chunkDXPTZB3Z_cjs = require('./chunk-DXPTZB3Z.cjs');
|
|
5
5
|
var React2 = require('react');
|
|
6
6
|
|
|
7
7
|
function _interopNamespace(e) {
|
|
@@ -28,16 +28,16 @@ var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
|
|
|
28
28
|
function installConsoleInterceptor(onMessage) {
|
|
29
29
|
if (typeof console === "undefined") return () => {
|
|
30
30
|
};
|
|
31
|
-
const original = console.error
|
|
31
|
+
const original = console.error;
|
|
32
32
|
const patched = (...args) => {
|
|
33
33
|
try {
|
|
34
|
-
const message =
|
|
35
|
-
if (message &&
|
|
34
|
+
const message = chunkAT6A77X3_cjs.formatConsoleArgs(args);
|
|
35
|
+
if (message && chunkAT6A77X3_cjs.isHydrationMessage(message)) {
|
|
36
36
|
onMessage(message, args);
|
|
37
37
|
}
|
|
38
38
|
} catch {
|
|
39
39
|
}
|
|
40
|
-
original(
|
|
40
|
+
original.apply(console, args);
|
|
41
41
|
};
|
|
42
42
|
console.error = patched;
|
|
43
43
|
return () => {
|
|
@@ -74,6 +74,32 @@ function createConsoleReporter() {
|
|
|
74
74
|
return sink;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
// src/react/capture.ts
|
|
78
|
+
var MAX_CAPTURED = 50;
|
|
79
|
+
var captured = /* @__PURE__ */ new Set();
|
|
80
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
81
|
+
var uninstall = null;
|
|
82
|
+
function startCapture() {
|
|
83
|
+
if (uninstall || typeof window === "undefined") return;
|
|
84
|
+
uninstall = installConsoleInterceptor((message) => {
|
|
85
|
+
if (captured.has(message) || captured.size >= MAX_CAPTURED) return;
|
|
86
|
+
captured.add(message);
|
|
87
|
+
for (const listener of [...listeners]) listener(message);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function subscribeCapture(listener) {
|
|
91
|
+
startCapture();
|
|
92
|
+
listeners.add(listener);
|
|
93
|
+
for (const message of [...captured]) listener(message);
|
|
94
|
+
return () => {
|
|
95
|
+
if (!listeners.delete(listener)) return;
|
|
96
|
+
if (listeners.size === 0 && uninstall) {
|
|
97
|
+
uninstall();
|
|
98
|
+
uninstall = null;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
77
103
|
// src/react/overlay.ts
|
|
78
104
|
var CONTAINER_ID = "why-hydration-overlay";
|
|
79
105
|
var CATEGORY_LABELS = {
|
|
@@ -89,7 +115,16 @@ var CATEGORY_LABELS = {
|
|
|
89
115
|
unknown: "Unknown"
|
|
90
116
|
};
|
|
91
117
|
var STYLES = `
|
|
92
|
-
:host {
|
|
118
|
+
:host {
|
|
119
|
+
all: initial;
|
|
120
|
+
/* The "all" shorthand deliberately excludes direction/unicode-bidi (CSS spec),
|
|
121
|
+
so a host page with <html dir="rtl"> would otherwise leak direction:rtl
|
|
122
|
+
into this shadow tree and flip flex/grid order + text alignment. Report
|
|
123
|
+
content is English, so the overlay always renders left-to-right,
|
|
124
|
+
independent of the host page's directionality. */
|
|
125
|
+
direction: ltr;
|
|
126
|
+
unicode-bidi: isolate;
|
|
127
|
+
}
|
|
93
128
|
* { box-sizing: border-box; }
|
|
94
129
|
.wh-panel {
|
|
95
130
|
position: fixed;
|
|
@@ -105,6 +140,8 @@ var STYLES = `
|
|
|
105
140
|
border-radius: 12px;
|
|
106
141
|
box-shadow: 0 12px 40px rgba(0,0,0,.5);
|
|
107
142
|
overflow: hidden;
|
|
143
|
+
direction: ltr;
|
|
144
|
+
text-align: left;
|
|
108
145
|
}
|
|
109
146
|
.wh-bottom-right { bottom: 16px; right: 16px; }
|
|
110
147
|
.wh-bottom-left { bottom: 16px; left: 16px; }
|
|
@@ -273,6 +310,7 @@ function createOverlay(options = {}) {
|
|
|
273
310
|
host.id = CONTAINER_ID;
|
|
274
311
|
host.setAttribute("data-why-hydration", "overlay");
|
|
275
312
|
host.setAttribute("aria-hidden", "false");
|
|
313
|
+
host.setAttribute("dir", "ltr");
|
|
276
314
|
const shadow = host.attachShadow({ mode: "open" });
|
|
277
315
|
const style = document.createElement("style");
|
|
278
316
|
style.textContent = STYLES;
|
|
@@ -324,6 +362,8 @@ function createOverlay(options = {}) {
|
|
|
324
362
|
countEl = null;
|
|
325
363
|
hintEl = null;
|
|
326
364
|
hintTextEl = null;
|
|
365
|
+
count = 0;
|
|
366
|
+
hintDismissed = false;
|
|
327
367
|
}
|
|
328
368
|
function push(report) {
|
|
329
369
|
ensureMounted();
|
|
@@ -392,6 +432,7 @@ function resolveReactSource(node) {
|
|
|
392
432
|
}
|
|
393
433
|
|
|
394
434
|
// src/react/controller.ts
|
|
435
|
+
var INSPECT_FALLBACK_MS = 50;
|
|
395
436
|
function buildIgnore(ignore) {
|
|
396
437
|
if (!ignore || ignore.length === 0) return void 0;
|
|
397
438
|
return (divergence) => {
|
|
@@ -415,11 +456,14 @@ var InspectorController = class {
|
|
|
415
456
|
this.started = false;
|
|
416
457
|
this.pendingContext = {};
|
|
417
458
|
this.messages = /* @__PURE__ */ new Set();
|
|
459
|
+
this.warnedRoots = /* @__PURE__ */ new Set();
|
|
418
460
|
this.settlingTimers = [];
|
|
461
|
+
this.inspectScheduled = false;
|
|
462
|
+
this.inspectTimer = null;
|
|
419
463
|
this.onRecoverableError = (error, info) => {
|
|
420
|
-
if (!
|
|
464
|
+
if (!chunkAT6A77X3_cjs.isDev) return;
|
|
421
465
|
const message = error instanceof Error ? error.message : String(error);
|
|
422
|
-
this.
|
|
466
|
+
this.rememberMessage(message);
|
|
423
467
|
this.mergeContext({
|
|
424
468
|
componentStack: info?.componentStack,
|
|
425
469
|
component: firstComponentFromStack(info?.componentStack),
|
|
@@ -428,33 +472,34 @@ var InspectorController = class {
|
|
|
428
472
|
this.scheduleInspect();
|
|
429
473
|
};
|
|
430
474
|
this.options = options;
|
|
431
|
-
this.collector = new
|
|
475
|
+
this.collector = new chunkAT6A77X3_cjs.ReportCollector({
|
|
432
476
|
maxReports: options.maxReports,
|
|
433
477
|
extra: options.classify,
|
|
434
|
-
ignore: buildIgnore(options
|
|
478
|
+
ignore: buildIgnore(options?.ignore)
|
|
435
479
|
});
|
|
436
480
|
}
|
|
437
481
|
start() {
|
|
438
|
-
if (this.started || !
|
|
482
|
+
if (this.started || !chunkAT6A77X3_cjs.isDev || typeof window === "undefined") return;
|
|
439
483
|
this.started = true;
|
|
440
|
-
this.pendingContext = {};
|
|
441
|
-
this.messages.clear();
|
|
442
484
|
if (this.options.onReport) {
|
|
443
|
-
this.collector.addSink(this.options.onReport);
|
|
485
|
+
this.cleanups.push(this.collector.addSink(this.options.onReport));
|
|
444
486
|
}
|
|
445
|
-
this.collector.addSink(createConsoleReporter());
|
|
487
|
+
this.cleanups.push(this.collector.addSink(createConsoleReporter()));
|
|
446
488
|
if (this.options.overlay !== false) {
|
|
447
489
|
const overlayOpts = typeof this.options.overlay === "object" ? this.options.overlay : {};
|
|
448
490
|
const handle = createOverlay(overlayOpts);
|
|
449
|
-
this.
|
|
450
|
-
|
|
491
|
+
this.cleanups.push(
|
|
492
|
+
this.collector.addSink(handle.push, { replay: true }),
|
|
493
|
+
() => handle.destroy()
|
|
494
|
+
);
|
|
451
495
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
496
|
+
this.cleanups.push(
|
|
497
|
+
subscribeCapture((message) => {
|
|
498
|
+
this.rememberMessage(message);
|
|
499
|
+
this.mergeContext({ reactMessage: message });
|
|
500
|
+
this.scheduleInspect();
|
|
501
|
+
})
|
|
502
|
+
);
|
|
458
503
|
this.scheduleSettlingInspections();
|
|
459
504
|
}
|
|
460
505
|
// React applies client values to mismatched subtrees via a client re-render a
|
|
@@ -469,18 +514,31 @@ var InspectorController = class {
|
|
|
469
514
|
this.settlingTimers.push(timer);
|
|
470
515
|
}
|
|
471
516
|
}
|
|
517
|
+
rememberMessage(message) {
|
|
518
|
+
if (this.messages.size >= MAX_CAPTURED && !this.messages.has(message)) {
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
this.messages.add(message);
|
|
522
|
+
}
|
|
472
523
|
mergeContext(ctx) {
|
|
473
524
|
this.pendingContext = {
|
|
474
|
-
componentStack:
|
|
475
|
-
component:
|
|
476
|
-
location:
|
|
477
|
-
reactMessage:
|
|
525
|
+
componentStack: ctx.componentStack ?? this.pendingContext.componentStack,
|
|
526
|
+
component: ctx.component ?? this.pendingContext.component,
|
|
527
|
+
location: ctx.location ?? this.pendingContext.location,
|
|
528
|
+
reactMessage: ctx.reactMessage ?? this.pendingContext.reactMessage
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
domContext() {
|
|
532
|
+
return {
|
|
533
|
+
componentStack: this.pendingContext.componentStack,
|
|
534
|
+
component: this.pendingContext.component,
|
|
535
|
+
location: this.pendingContext.location
|
|
478
536
|
};
|
|
479
537
|
}
|
|
480
538
|
stop() {
|
|
481
539
|
for (const timer of this.settlingTimers.splice(0)) clearTimeout(timer);
|
|
540
|
+
this.clearScheduledInspect();
|
|
482
541
|
for (const cleanup of this.cleanups.splice(0)) cleanup();
|
|
483
|
-
this.messages.clear();
|
|
484
542
|
this.started = false;
|
|
485
543
|
}
|
|
486
544
|
getReports() {
|
|
@@ -494,36 +552,66 @@ var InspectorController = class {
|
|
|
494
552
|
if (!this.started || typeof document === "undefined" || this.collector.isFull) {
|
|
495
553
|
return;
|
|
496
554
|
}
|
|
497
|
-
const
|
|
555
|
+
const configured = this.options.roots;
|
|
556
|
+
const selectors = configured ?? snapshotSelectors();
|
|
557
|
+
const context = this.domContext();
|
|
498
558
|
const seen = /* @__PURE__ */ new Set();
|
|
499
559
|
for (const selector of selectors) {
|
|
500
|
-
|
|
560
|
+
let root = null;
|
|
561
|
+
try {
|
|
562
|
+
root = document.querySelector(selector);
|
|
563
|
+
} catch {
|
|
564
|
+
this.warnRoot(selector, `"${selector}" is not a valid CSS selector.`);
|
|
565
|
+
continue;
|
|
566
|
+
}
|
|
501
567
|
if (!root || seen.has(root)) continue;
|
|
502
568
|
seen.add(root);
|
|
503
|
-
|
|
569
|
+
if (configured && chunkDXPTZB3Z_cjs.getServerHtmlForRoot(root) == null) {
|
|
570
|
+
this.warnRoot(
|
|
571
|
+
selector,
|
|
572
|
+
`no server HTML was captured for "${selector}". Add it to the \`selectors\` prop of <HydrationSnapshotScript> so the server markup for that root is snapshotted.`
|
|
573
|
+
);
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
chunkAT6A77X3_cjs.inspectRoot(
|
|
504
577
|
root,
|
|
505
578
|
this.collector,
|
|
506
|
-
|
|
579
|
+
context,
|
|
507
580
|
(divergence) => resolveReactSource(divergence.element ?? null)
|
|
508
581
|
);
|
|
509
582
|
}
|
|
510
583
|
for (const message of this.messages) {
|
|
511
|
-
|
|
584
|
+
chunkAT6A77X3_cjs.reportFromMessage(message, this.collector, this.pendingContext);
|
|
512
585
|
}
|
|
513
586
|
}
|
|
587
|
+
warnRoot(selector, detail) {
|
|
588
|
+
if (this.warnedRoots.has(selector)) return;
|
|
589
|
+
this.warnedRoots.add(selector);
|
|
590
|
+
console.warn(`[why-hydration] Skipping root: ${detail}`);
|
|
591
|
+
}
|
|
514
592
|
scheduleInspect() {
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
593
|
+
if (this.inspectScheduled) return;
|
|
594
|
+
this.inspectScheduled = true;
|
|
595
|
+
const run = () => {
|
|
596
|
+
if (!this.inspectScheduled) return;
|
|
597
|
+
this.clearScheduledInspect();
|
|
598
|
+
this.inspectAllRoots();
|
|
599
|
+
};
|
|
600
|
+
if (typeof requestAnimationFrame === "function") requestAnimationFrame(run);
|
|
601
|
+
this.inspectTimer = setTimeout(run, INSPECT_FALLBACK_MS);
|
|
602
|
+
}
|
|
603
|
+
clearScheduledInspect() {
|
|
604
|
+
this.inspectScheduled = false;
|
|
605
|
+
if (this.inspectTimer != null) {
|
|
606
|
+
clearTimeout(this.inspectTimer);
|
|
607
|
+
this.inspectTimer = null;
|
|
520
608
|
}
|
|
521
609
|
}
|
|
522
610
|
};
|
|
523
611
|
function snapshotSelectors() {
|
|
524
|
-
const snapshot =
|
|
612
|
+
const snapshot = chunkDXPTZB3Z_cjs.readSnapshot();
|
|
525
613
|
const keys = snapshot ? Object.keys(snapshot.roots) : [];
|
|
526
|
-
return keys.length > 0 ? keys : [...
|
|
614
|
+
return keys.length > 0 ? keys : [...chunkDXPTZB3Z_cjs.DEFAULT_SNAPSHOT_SELECTORS];
|
|
527
615
|
}
|
|
528
616
|
function firstComponentFromStack(stack) {
|
|
529
617
|
if (!stack) return void 0;
|
|
@@ -532,20 +620,13 @@ function firstComponentFromStack(stack) {
|
|
|
532
620
|
}
|
|
533
621
|
function InspectorImpl(props) {
|
|
534
622
|
const { children, overlay, onReport, ignore, classify, maxReports } = props;
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
overlay,
|
|
539
|
-
onReport,
|
|
540
|
-
ignore,
|
|
541
|
-
classify,
|
|
542
|
-
maxReports
|
|
543
|
-
});
|
|
544
|
-
controllerRef.current.start();
|
|
545
|
-
}
|
|
623
|
+
startCapture();
|
|
624
|
+
const optionsRef = React2__namespace.useRef({});
|
|
625
|
+
optionsRef.current = { overlay, onReport, ignore, classify, maxReports };
|
|
546
626
|
React2__namespace.useEffect(() => {
|
|
547
|
-
const controller =
|
|
548
|
-
|
|
627
|
+
const controller = new InspectorController(optionsRef.current);
|
|
628
|
+
controller.start();
|
|
629
|
+
return () => controller.stop();
|
|
549
630
|
}, []);
|
|
550
631
|
return React2__namespace.createElement(React2__namespace.Fragment, null, children);
|
|
551
632
|
}
|
|
@@ -566,7 +647,10 @@ function createHydrationInspector(options = {}) {
|
|
|
566
647
|
const controller = new InspectorController(options);
|
|
567
648
|
controller.start();
|
|
568
649
|
function Provider(props) {
|
|
569
|
-
React2__namespace.useEffect(() =>
|
|
650
|
+
React2__namespace.useEffect(() => {
|
|
651
|
+
controller.start();
|
|
652
|
+
return () => controller.stop();
|
|
653
|
+
}, []);
|
|
570
654
|
return React2__namespace.createElement(React2__namespace.Fragment, null, props.children);
|
|
571
655
|
}
|
|
572
656
|
return {
|
|
@@ -577,5 +661,5 @@ function createHydrationInspector(options = {}) {
|
|
|
577
661
|
|
|
578
662
|
exports.HydrationInspector = HydrationInspector;
|
|
579
663
|
exports.createHydrationInspector = createHydrationInspector;
|
|
580
|
-
//# sourceMappingURL=chunk-
|
|
581
|
-
//# sourceMappingURL=chunk-
|
|
664
|
+
//# sourceMappingURL=chunk-OFVFNPE6.cjs.map
|
|
665
|
+
//# sourceMappingURL=chunk-OFVFNPE6.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/react/console.ts","../src/react/capture.ts","../src/react/overlay.ts","../src/react/fiber.ts","../src/react/controller.ts","../src/react/inspector.tsx","../src/react/index.tsx"],"names":["formatConsoleArgs","isHydrationMessage","isDev","ReportCollector","getServerHtmlForRoot","inspectRoot","reportFromMessage","readSnapshot","DEFAULT_SNAPSHOT_SELECTORS","React","React2"],"mappings":"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","file":"chunk-OFVFNPE6.cjs","sourcesContent":["import { formatConsoleArgs, isHydrationMessage } from '../core/react-message';\nimport type { HydrationReport } from '../core/types';\nimport type { ReportSink } from '../core/report';\n\ntype ErrorFn = (...args: unknown[]) => void;\n\nexport function installConsoleInterceptor(\n onMessage: (message: string, args: readonly unknown[]) => void,\n): () => void {\n if (typeof console === 'undefined') return () => {};\n const original = console.error;\n const patched: ErrorFn = (...args: unknown[]) => {\n try {\n const message = formatConsoleArgs(args);\n if (message && isHydrationMessage(message)) {\n onMessage(message, args);\n }\n } catch {\n /* never let interception break normal logging */\n }\n // `apply` rather than a bound copy, so uninstalling can hand back the exact\n // function we replaced. Restoring a bound copy instead leaves a wrapper\n // behind on every install/uninstall cycle.\n original.apply(console, args);\n };\n console.error = patched as typeof console.error;\n\n return () => {\n if (console.error === (patched as typeof console.error)) {\n console.error = original as typeof console.error;\n }\n };\n}\n\nconst BADGE = 'color:#f59e0b;font-weight:bold';\nconst DIM = 'color:#9ca3af';\n\nexport function createConsoleReporter(): ReportSink {\n const sink: ReportSink = (report: HydrationReport) => {\n const title = `%c⬡ why-hydration%c ${report.cause.category} — ${report.node.path}`;\n console.group(title, BADGE, DIM);\n console.log('%cServer:%c', 'color:#fb7185', '', report.server ?? '(none)');\n console.log('%cClient:%c', 'color:#4ade80', '', report.client ?? '(none)');\n if (report.component) {\n console.log('%cComponent:%c', DIM, '', `<${report.component}>`);\n }\n if (report.location?.file) {\n const loc = report.location.line\n ? `${report.location.file}:${report.location.line}`\n : report.location.file;\n console.log('%cSource:%c', DIM, '', loc);\n }\n console.log('%cWhy:%c', DIM, '', report.cause.explanation);\n console.log('%cFix:%c', 'color:#86efac', '', report.cause.suggestion);\n if (report.cause.docsUrl) {\n console.log('%cDocs:%c', DIM, '', report.cause.docsUrl);\n }\n if (report.componentStack) {\n console.log('%cComponent stack:%c', DIM, '', report.componentStack);\n }\n console.groupEnd();\n };\n return sink;\n}\n","import { installConsoleInterceptor } from './console';\n\n/**\n * Module-scoped capture of React's hydration warnings.\n *\n * React logs a mismatch while it hydrates the tree *below* the inspector, which\n * is long before any effect runs — so interception has to begin during render.\n * Render is also the one place a component may be invoked more than once per\n * mount (Strict Mode renders twice, with fresh hook state each time), so the\n * state lives here rather than on an instance: a second call is then a genuine\n * no-op instead of a second interceptor that nobody owns and nobody removes.\n */\n\nexport type CaptureListener = (message: string) => void;\n\n// Hydration warnings are emitted once per page load; this only guards against\n// an app that logs matching messages in a loop. Past the cap a message is\n// dropped outright rather than recorded-but-forwarded — see `startCapture`.\nexport const MAX_CAPTURED = 50;\n\nconst captured = new Set<string>();\nconst listeners = new Set<CaptureListener>();\nlet uninstall: (() => void) | null = null;\n\n/** Start intercepting. Idempotent, and safe to call from render. */\nexport function startCapture(): void {\n if (uninstall || typeof window === 'undefined') return;\n uninstall = installConsoleInterceptor((message) => {\n // The cap gates the *notification*, not just the recording. Forwarding a\n // message we decline to record would defeat the dedup above at exactly the\n // point the cap exists to protect: every repeat past the cap would look\n // new, and each one costs a listener a full inspection pass.\n if (captured.has(message) || captured.size >= MAX_CAPTURED) return;\n captured.add(message);\n for (const listener of [...listeners]) listener(message);\n });\n}\n\n/**\n * Subscribe to hydration messages. Whatever was captured before subscribing is\n * replayed immediately, so a listener attached after hydration — or re-attached\n * across a Strict Mode stop/start cycle — still sees what React logged.\n */\nexport function subscribeCapture(listener: CaptureListener): () => void {\n startCapture();\n listeners.add(listener);\n for (const message of [...captured]) listener(message);\n\n return () => {\n if (!listeners.delete(listener)) return;\n // The backlog outlives the last subscriber on purpose: hydration happens\n // once per page, so a remounted inspector still needs those messages.\n // Only the console patch is handed back. The live set is the count — a\n // separate counter would drift the moment one listener subscribed twice\n // (`Set.add` dedupes, a counter does not) and strand the patch forever.\n if (listeners.size === 0 && uninstall) {\n uninstall();\n uninstall = null;\n }\n };\n}\n\n/** Drop the interceptor and the recorded backlog (tests, hot reload). */\nexport function resetCapture(): void {\n uninstall?.();\n uninstall = null;\n listeners.clear();\n captured.clear();\n}\n","import type { HydrationReport } from '../core/types';\n\nexport interface OverlayOptions {\n position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';\n}\n\nexport interface OverlayHandle {\n push: (report: HydrationReport) => void;\n destroy: () => void;\n}\n\nconst CONTAINER_ID = 'why-hydration-overlay';\n\nconst CATEGORY_LABELS: Record<string, string> = {\n 'non-deterministic-value': 'Non-deterministic value',\n 'date-time': 'Date / time',\n 'locale-format': 'Locale formatting',\n 'browser-only-api': 'Browser-only API',\n 'viewport-branching': 'Viewport branching',\n 'invalid-html-nesting': 'Invalid HTML nesting',\n 'whitespace-minification': 'Whitespace / minification',\n 'third-party-dom-mutation': 'Third-party DOM mutation',\n 'attribute-mismatch': 'Attribute mismatch',\n unknown: 'Unknown',\n};\n\nconst STYLES = `\n:host {\n all: initial;\n /* The \"all\" shorthand deliberately excludes direction/unicode-bidi (CSS spec),\n so a host page with <html dir=\"rtl\"> would otherwise leak direction:rtl\n into this shadow tree and flip flex/grid order + text alignment. Report\n content is English, so the overlay always renders left-to-right,\n independent of the host page's directionality. */\n direction: ltr;\n unicode-bidi: isolate;\n}\n* { box-sizing: border-box; }\n.wh-panel {\n position: fixed;\n z-index: 2147483647;\n width: min(420px, calc(100vw - 32px));\n max-height: min(70vh, 640px);\n display: flex;\n flex-direction: column;\n font: 13px/1.5 ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif;\n color: #e5e7eb;\n background: #0b0f17;\n border: 1px solid #1f2937;\n border-radius: 12px;\n box-shadow: 0 12px 40px rgba(0,0,0,.5);\n overflow: hidden;\n direction: ltr;\n text-align: left;\n}\n.wh-bottom-right { bottom: 16px; right: 16px; }\n.wh-bottom-left { bottom: 16px; left: 16px; }\n.wh-top-right { top: 16px; right: 16px; }\n.wh-top-left { top: 16px; left: 16px; }\n.wh-header {\n display: flex; align-items: center; gap: 8px;\n padding: 10px 12px;\n background: linear-gradient(180deg, #151b26, #0d1220);\n border-bottom: 1px solid #1f2937;\n}\n.wh-dot { width: 8px; height: 8px; border-radius: 50%; background: #f59e0b; flex: none; }\n.wh-title { font-weight: 600; color: #f3f4f6; }\n.wh-count {\n margin-left: auto; font-size: 11px; color: #9ca3af;\n background: #111827; border: 1px solid #1f2937; border-radius: 999px;\n padding: 1px 8px;\n}\n.wh-btn {\n appearance: none; border: 1px solid #1f2937; background: #111827;\n color: #9ca3af; border-radius: 6px; cursor: pointer;\n font-size: 12px; padding: 3px 8px;\n}\n.wh-btn:hover { color: #f3f4f6; border-color: #374151; }\n.wh-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 8px; display: flex; flex-direction: column; gap: 8px; }\n.wh-card { flex: 0 0 auto; border: 1px solid #1f2937; border-radius: 10px; background: #0f1521; overflow: hidden; }\n.wh-card-head { display: flex; align-items: center; gap: 8px; padding: 8px 10px; }\n.wh-cat {\n font-weight: 600; color: #fbbf24; font-size: 12px;\n}\n.wh-conf { margin-left: auto; font-size: 11px; color: #6b7280; }\n.wh-body { padding: 0 10px 10px; }\n.wh-where { font-size: 11px; color: #9ca3af; word-break: break-all; margin-bottom: 4px; }\n.wh-where code { color: #93c5fd; }\n.wh-comp { color: #f3f4f6; font-weight: 600; }\n.wh-loc { font-size: 11px; color: #7dd3fc; word-break: break-all; margin-bottom: 8px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }\n.wh-diff { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-bottom: 8px; }\n.wh-side { border-radius: 8px; padding: 6px 8px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; word-break: break-word; }\n.wh-server { background: rgba(244,63,94,.08); border: 1px solid rgba(244,63,94,.35); }\n.wh-client { background: rgba(34,197,94,.08); border: 1px solid rgba(34,197,94,.35); }\n.wh-side .wh-label { display: block; font-family: inherit; font-size: 9px; text-transform: uppercase; letter-spacing: .04em; margin-bottom: 3px; }\n.wh-server .wh-label { color: #fb7185; }\n.wh-client .wh-label { color: #4ade80; }\n.wh-explain { color: #cbd5e1; margin-bottom: 8px; }\n.wh-fix { color: #e5e7eb; background: #111827; border-left: 3px solid #22c55e; border-radius: 4px; padding: 6px 8px; }\n.wh-fix strong { color: #86efac; }\n.wh-docs { display: inline-block; margin-top: 6px; color: #60a5fa; text-decoration: none; font-size: 11px; }\n.wh-docs:hover { text-decoration: underline; }\n.wh-empty-value { color: #6b7280; font-style: italic; }\n.wh-hint {\n display: none; align-items: center; gap: 8px;\n padding: 7px 12px; font-size: 11px; color: #cbd5e1;\n background: #0d1220; border-top: 1px solid #1f2937;\n animation: wh-fade .2s ease;\n}\n.wh-hint.wh-show { display: flex; }\n.wh-hint-text { flex: 1; }\n.wh-hint-x {\n appearance: none; border: 0; background: transparent; cursor: pointer;\n color: #9ca3af; font-size: 14px; line-height: 1; padding: 2px 4px;\n}\n.wh-hint-x:hover { color: #f3f4f6; }\n@keyframes wh-fade { from { opacity: 0 } to { opacity: 1 } }\n@media (max-width: 420px) {\n .wh-panel { width: auto; max-height: min(80vh, 640px); }\n .wh-bottom-right, .wh-bottom-left { left: 8px; right: 8px; }\n .wh-top-right, .wh-top-left { left: 8px; right: 8px; }\n .wh-diff { grid-template-columns: 1fr; }\n}\n`;\n\nfunction el<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n className?: string,\n text?: string,\n): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag);\n if (className) node.className = className;\n if (text != null) node.textContent = text;\n return node;\n}\n\nfunction shortenPath(file: string): string {\n const normalized = file.replace(/\\\\/g, '/');\n const marker = normalized.match(/(?:^|\\/)(?:src|app|pages|components)\\//);\n if (marker && marker.index != null) {\n return normalized.slice(marker.index).replace(/^\\//, '');\n }\n const parts = normalized.split('/');\n return parts.slice(-2).join('/');\n}\n\nfunction renderValue(value: string | null): HTMLElement {\n if (value == null || value === '') {\n return el('span', 'wh-empty-value', value === '' ? '(empty)' : '(none)');\n }\n const span = document.createElement('span');\n span.textContent = value;\n return span;\n}\n\nfunction renderCard(report: HydrationReport): HTMLElement {\n const card = el('div', 'wh-card');\n\n const head = el('div', 'wh-card-head');\n head.appendChild(\n el('span', 'wh-cat', CATEGORY_LABELS[report.cause.category] ?? 'Mismatch'),\n );\n head.appendChild(\n el('span', 'wh-conf', `${Math.round(report.cause.confidence * 100)}%`),\n );\n card.appendChild(head);\n\n const body = el('div', 'wh-body');\n\n const where = el('div', 'wh-where');\n if (report.component) {\n where.appendChild(el('strong', 'wh-comp', `<${report.component}>`));\n where.append(' · ');\n } else if (report.node.tagName) {\n where.append(`<${report.node.tagName.toLowerCase()}> · `);\n }\n const code = el('code');\n code.textContent = report.node.path;\n where.appendChild(code);\n if (report.node.attribute) {\n where.append(` · @${report.node.attribute}`);\n }\n body.appendChild(where);\n\n if (report.location?.file) {\n const loc = el('div', 'wh-loc');\n const file = shortenPath(report.location.file);\n loc.textContent = report.location.line\n ? `${file}:${report.location.line}`\n : file;\n body.appendChild(loc);\n }\n\n const diff = el('div', 'wh-diff');\n const server = el('div', 'wh-side wh-server');\n server.appendChild(el('span', 'wh-label', 'Server'));\n server.appendChild(renderValue(report.server));\n const client = el('div', 'wh-side wh-client');\n client.appendChild(el('span', 'wh-label', 'Client'));\n client.appendChild(renderValue(report.client));\n diff.appendChild(server);\n diff.appendChild(client);\n body.appendChild(diff);\n\n body.appendChild(el('div', 'wh-explain', report.cause.explanation));\n\n const fix = el('div', 'wh-fix');\n const strong = el('strong');\n strong.textContent = 'Fix: ';\n fix.appendChild(strong);\n fix.append(report.cause.suggestion);\n body.appendChild(fix);\n\n if (report.cause.docsUrl && /^https?:\\/\\//i.test(report.cause.docsUrl)) {\n const a = el('a', 'wh-docs', 'Learn more →');\n a.href = report.cause.docsUrl;\n a.target = '_blank';\n a.rel = 'noreferrer noopener';\n body.appendChild(a);\n }\n\n card.appendChild(body);\n return card;\n}\n\nexport function createOverlay(options: OverlayOptions = {}): OverlayHandle {\n const position = options.position ?? 'bottom-right';\n let host: HTMLElement | null = null;\n let listEl: HTMLElement | null = null;\n let countEl: HTMLElement | null = null;\n let hintEl: HTMLElement | null = null;\n let hintTextEl: HTMLElement | null = null;\n let hintCheckTimer: ReturnType<typeof setTimeout> | null = null;\n let hintDismissed = false;\n let count = 0;\n\n function ensureMounted(): void {\n if (host) return;\n document.getElementById(CONTAINER_ID)?.remove();\n host = document.createElement('div');\n host.id = CONTAINER_ID;\n host.setAttribute('data-why-hydration', 'overlay');\n host.setAttribute('aria-hidden', 'false');\n // Belt and braces with the `:host { direction: ltr }` rule below: on an RTL\n // host page a stylesheet targeting the host element from the outer document\n // outranks `:host`, but the attribute still wins. Report content is\n // English, so the overlay stays LTR whatever the page direction.\n host.setAttribute('dir', 'ltr');\n const shadow = host.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = STYLES;\n shadow.appendChild(style);\n\n const panel = el('div', `wh-panel wh-${position}`);\n panel.setAttribute('role', 'dialog');\n panel.setAttribute('aria-label', 'Hydration mismatch diagnostics');\n\n const header = el('div', 'wh-header');\n header.appendChild(el('span', 'wh-dot'));\n header.appendChild(el('span', 'wh-title', 'Hydration mismatch'));\n countEl = el('span', 'wh-count', '0');\n header.appendChild(countEl);\n const close = el('button', 'wh-btn', 'Dismiss');\n close.setAttribute('aria-label', 'Dismiss diagnostics overlay');\n close.addEventListener('click', () => destroy());\n header.appendChild(close);\n panel.appendChild(header);\n\n listEl = el('div', 'wh-list');\n panel.appendChild(listEl);\n\n hintEl = el('div', 'wh-hint');\n hintTextEl = el('span', 'wh-hint-text');\n hintEl.appendChild(hintTextEl);\n const hintX = el('button', 'wh-hint-x', '✕');\n hintX.setAttribute('aria-label', 'Dismiss hint');\n hintX.addEventListener('click', () => dismissHint());\n hintEl.appendChild(hintX);\n panel.appendChild(hintEl);\n\n shadow.appendChild(panel);\n document.body.appendChild(host);\n\n host.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Escape') destroy();\n });\n }\n\n function dismissHint(): void {\n hintDismissed = true;\n hintEl?.classList.remove('wh-show');\n }\n\n // Show a persistent \"scroll for more\" hint once there are enough issues that\n // the panel is guaranteed to overflow (cards are ~150px+, panel caps at\n // ~640px, so 4+ always scroll). Count-based — no async layout measurement,\n // no timers — and only ever ADDS the class. It's removed only by its own ✕\n // button (dismissHint), which satisfies the \"close button\" requirement.\n function updateHint(): void {\n if (!hintEl || !hintTextEl || hintDismissed) return;\n hintTextEl.textContent = `↓ ${count} issues — scroll to see all`;\n if (count >= 4) hintEl.classList.add('wh-show');\n }\n\n // Tears the panel down to nothing — including the counters, which describe\n // the cards in the list rather than the reports ever seen. `push` re-mounts\n // an empty panel, so a stale count would have it claim \"14 issues — scroll to\n // see all\" above a single card that does not scroll.\n function destroy(): void {\n if (hintCheckTimer) clearTimeout(hintCheckTimer);\n hintCheckTimer = null;\n host?.remove();\n host = null;\n listEl = null;\n countEl = null;\n hintEl = null;\n hintTextEl = null;\n count = 0;\n hintDismissed = false;\n }\n\n function push(report: HydrationReport): void {\n ensureMounted();\n count += 1;\n if (countEl) countEl.textContent = String(count);\n listEl?.appendChild(renderCard(report));\n // Debounce: reports arrive in bursts across the settling window. Evaluate\n // the hint once things go quiet, after layout has settled, so the overflow\n // measurement is accurate.\n if (hintCheckTimer) clearTimeout(hintCheckTimer);\n hintCheckTimer = setTimeout(updateHint, 400);\n }\n\n return { push, destroy };\n}\n","import type { DetectionContext } from '../core/types';\n\n// Best-effort: walk the React fiber attached to a DOM node to recover the\n// owning component name and (in React 18 dev builds) its source file/line.\n// This is what turns a bare selector path into \"which component / file\".\n// Purely read-only, dev-only, and defensive — any failure returns {}.\n\ninterface Fiber {\n type?: unknown;\n return?: Fiber | null;\n _debugSource?: { fileName?: string; lineNumber?: number; columnNumber?: number };\n _debugOwner?: Fiber | null;\n}\n\nfunction getFiber(node: Node): Fiber | null {\n for (const key in node) {\n if (\n key.startsWith('__reactFiber$') ||\n key.startsWith('__reactInternalInstance$')\n ) {\n return (node as unknown as Record<string, Fiber>)[key] ?? null;\n }\n }\n return null;\n}\n\nfunction componentName(type: unknown): string | undefined {\n if (!type || typeof type === 'string') return undefined;\n if (typeof type === 'function') {\n const fn = type as { displayName?: string; name?: string };\n return fn.displayName || fn.name || undefined;\n }\n if (typeof type === 'object') {\n const obj = type as {\n displayName?: string;\n render?: { displayName?: string; name?: string };\n type?: unknown;\n };\n if (obj.displayName) return obj.displayName;\n if (obj.render) return obj.render.displayName || obj.render.name;\n if (obj.type) return componentName(obj.type);\n }\n return undefined;\n}\n\n/**\n * Resolve the component and source location responsible for a live DOM node.\n * Returns a {@link DetectionContext} fragment (`component`, `location`) that the\n * reporter merges into the report.\n */\nexport function resolveReactSource(node: Element | null): DetectionContext {\n if (!node) return {};\n try {\n let fiber: Fiber | null = getFiber(node);\n let component: string | undefined;\n let location: DetectionContext['location'];\n let hops = 0;\n while (fiber && hops < 80) {\n if (!component) {\n const name = componentName(fiber.type);\n // Skip built-in host components (div, span…) — we want the nearest\n // user component that owns this node.\n if (name && !/^[a-z]/.test(name)) component = name;\n }\n if (!location && fiber._debugSource?.fileName) {\n location = {\n file: fiber._debugSource.fileName,\n line: fiber._debugSource.lineNumber,\n column: fiber._debugSource.columnNumber,\n };\n }\n if (component && location) break;\n fiber = fiber.return ?? null;\n hops += 1;\n }\n const result: DetectionContext = {};\n if (component) result.component = component;\n if (location) result.location = location;\n return result;\n } catch {\n return {};\n }\n}\n","import { inspectRoot, reportFromMessage } from '../core/inspect';\nimport { ReportCollector } from '../core/report';\nimport {\n DEFAULT_SNAPSHOT_SELECTORS,\n getServerHtmlForRoot,\n readSnapshot,\n} from '../core/snapshot';\nimport { isDev } from '../core/env';\nimport type {\n Classifier,\n DetectionContext,\n Divergence,\n HydrationReport,\n} from '../core/types';\nimport { MAX_CAPTURED, subscribeCapture } from './capture';\nimport { createConsoleReporter } from './console';\nimport { createOverlay, type OverlayOptions } from './overlay';\nimport { resolveReactSource } from './fiber';\n\nconst INSPECT_FALLBACK_MS = 50;\n\nexport interface InspectorOptions {\n overlay?: boolean | OverlayOptions;\n onReport?: (report: HydrationReport) => void;\n ignore?: Array<string | ((node: Element) => boolean)>;\n classify?: Classifier[];\n maxReports?: number;\n roots?: string[];\n}\n\nfunction buildIgnore(\n ignore: InspectorOptions['ignore'],\n): ((d: Divergence) => boolean) | undefined {\n if (!ignore || ignore.length === 0) return undefined;\n return (divergence: Divergence): boolean => {\n const node = divergence.element ?? null;\n for (const rule of ignore) {\n if (typeof rule === 'function') {\n if (node && rule(node)) return true;\n } else if (node) {\n try {\n if (node.matches(rule) || node.closest(rule)) return true;\n } catch {\n /* invalid selector */\n }\n }\n }\n return false;\n };\n}\n\nexport class InspectorController {\n private readonly collector: ReportCollector;\n private readonly options: InspectorOptions;\n private readonly cleanups: Array<() => void> = [];\n private started = false;\n private pendingContext: DetectionContext = {};\n private readonly messages = new Set<string>();\n private readonly warnedRoots = new Set<string>();\n private settlingTimers: Array<ReturnType<typeof setTimeout>> = [];\n private inspectScheduled = false;\n private inspectTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(options: InspectorOptions = {}) {\n this.options = options;\n this.collector = new ReportCollector({\n maxReports: options.maxReports,\n extra: options.classify,\n ignore: buildIgnore(options?.ignore),\n });\n }\n\n start(): void {\n if (this.started || !isDev || typeof window === 'undefined') return;\n this.started = true;\n\n if (this.options.onReport) {\n this.cleanups.push(this.collector.addSink(this.options.onReport));\n }\n this.cleanups.push(this.collector.addSink(createConsoleReporter()));\n if (this.options.overlay !== false) {\n const overlayOpts: OverlayOptions =\n typeof this.options.overlay === 'object' ? this.options.overlay : {};\n const handle = createOverlay(overlayOpts);\n // Replay: a fresh overlay must show the reports collected before it.\n this.cleanups.push(\n this.collector.addSink(handle.push, { replay: true }),\n () => handle.destroy(),\n );\n }\n\n // Replays whatever React logged before this controller existed, which is\n // the normal case: the mismatch is reported while the tree hydrates.\n this.cleanups.push(\n subscribeCapture((message) => {\n this.rememberMessage(message);\n this.mergeContext({ reactMessage: message });\n this.scheduleInspect();\n }),\n );\n\n this.scheduleSettlingInspections();\n }\n\n // React applies client values to mismatched subtrees via a client re-render a\n // few hundred ms after the initial hydration commit. We diff once per frame\n // and then across this short \"settling window\" to catch that, deduped. This\n // is a bounded, one-shot window — NOT a standing observer — so DOM changes\n // from later app state are never mistaken for hydration mismatches.\n private scheduleSettlingInspections(): void {\n this.scheduleInspect();\n for (const delay of [80, 250, 700, 1500]) {\n const timer = setTimeout(() => this.inspectAllRoots(), delay);\n this.settlingTimers.push(timer);\n }\n }\n\n onRecoverableError = (\n error: unknown,\n info?: { componentStack?: string },\n ): void => {\n if (!isDev) return;\n const message = error instanceof Error ? error.message : String(error);\n this.rememberMessage(message);\n this.mergeContext({\n componentStack: info?.componentStack,\n component: firstComponentFromStack(info?.componentStack),\n reactMessage: message,\n });\n this.scheduleInspect();\n };\n\n private rememberMessage(message: string): void {\n if (this.messages.size >= MAX_CAPTURED && !this.messages.has(message)) {\n return;\n }\n this.messages.add(message);\n }\n\n private mergeContext(ctx: DetectionContext): void {\n this.pendingContext = {\n componentStack: ctx.componentStack ?? this.pendingContext.componentStack,\n component: ctx.component ?? this.pendingContext.component,\n location: ctx.location ?? this.pendingContext.location,\n reactMessage: ctx.reactMessage ?? this.pendingContext.reactMessage,\n };\n }\n\n private domContext(): DetectionContext {\n return {\n componentStack: this.pendingContext.componentStack,\n component: this.pendingContext.component,\n location: this.pendingContext.location,\n };\n }\n\n stop(): void {\n for (const timer of this.settlingTimers.splice(0)) clearTimeout(timer);\n this.clearScheduledInspect();\n for (const cleanup of this.cleanups.splice(0)) cleanup();\n this.started = false;\n }\n\n getReports(): readonly HydrationReport[] {\n return this.collector.getReports();\n }\n\n inspectNow(context: DetectionContext = {}): void {\n this.mergeContext(context);\n this.inspectAllRoots();\n }\n\n private inspectAllRoots(): void {\n if (\n !this.started ||\n typeof document === 'undefined' ||\n this.collector.isFull\n ) {\n return;\n }\n // 1) DOM diff — every visible mismatch (text/attribute/structure), precise\n // path + component/source from the fiber.\n const configured = this.options.roots;\n const selectors = configured ?? snapshotSelectors();\n const context = this.domContext();\n const seen = new Set<Element>();\n for (const selector of selectors) {\n let root: Element | null = null;\n try {\n root = document.querySelector(selector);\n } catch {\n this.warnRoot(selector, `\"${selector}\" is not a valid CSS selector.`);\n continue;\n }\n if (!root || seen.has(root)) continue;\n seen.add(root);\n if (configured && getServerHtmlForRoot(root) == null) {\n this.warnRoot(\n selector,\n `no server HTML was captured for \"${selector}\". Add it to the ` +\n '`selectors` prop of <HydrationSnapshotScript> so the server ' +\n 'markup for that root is snapshotted.',\n );\n continue;\n }\n inspectRoot(root, this.collector, context, (divergence) =>\n resolveReactSource(divergence.element ?? null),\n );\n }\n\n for (const message of this.messages) {\n reportFromMessage(message, this.collector, this.pendingContext);\n }\n }\n\n private warnRoot(selector: string, detail: string): void {\n if (this.warnedRoots.has(selector)) return;\n this.warnedRoots.add(selector);\n // eslint-disable-next-line no-console\n console.warn(`[why-hydration] Skipping root: ${detail}`);\n }\n\n private scheduleInspect(): void {\n if (this.inspectScheduled) return;\n this.inspectScheduled = true;\n const run = () => {\n if (!this.inspectScheduled) return;\n this.clearScheduledInspect();\n this.inspectAllRoots();\n };\n if (typeof requestAnimationFrame === 'function') requestAnimationFrame(run);\n this.inspectTimer = setTimeout(run, INSPECT_FALLBACK_MS);\n }\n\n private clearScheduledInspect(): void {\n this.inspectScheduled = false;\n if (this.inspectTimer != null) {\n clearTimeout(this.inspectTimer);\n this.inspectTimer = null;\n }\n }\n}\n\nfunction snapshotSelectors(): string[] {\n const snapshot = readSnapshot();\n const keys = snapshot ? Object.keys(snapshot.roots) : [];\n return keys.length > 0 ? keys : [...DEFAULT_SNAPSHOT_SELECTORS];\n}\n\nfunction firstComponentFromStack(stack?: string): string | undefined {\n if (!stack) return undefined;\n const match = /\\n?\\s*(?:at|in)\\s+([A-Za-z0-9_$]+)/.exec(stack);\n return match?.[1];\n}\n","import * as React from 'react';\nimport type { Classifier, HydrationReport } from '../core/types';\nimport { startCapture } from './capture';\nimport { InspectorController, type InspectorOptions } from './controller';\nimport type { OverlayOptions } from './overlay';\n\nexport interface HydrationInspectorProps {\n children: React.ReactNode;\n overlay?: boolean | OverlayOptions;\n onReport?: (report: HydrationReport) => void;\n ignore?: Array<string | ((node: Element) => boolean)>;\n classify?: Classifier[];\n maxReports?: number;\n}\n\nexport function InspectorImpl(\n props: HydrationInspectorProps,\n): React.ReactElement {\n const { children, overlay, onReport, ignore, classify, maxReports } = props;\n\n // The one thing that cannot wait for an effect: React logs the mismatch while\n // it hydrates the children below, and effects run after that. Capture is\n // module-scoped and idempotent, so Strict Mode — which renders twice with\n // fresh hook state — starts it once instead of leaving a stray interceptor.\n startCapture();\n\n const optionsRef = React.useRef<InspectorOptions>({});\n optionsRef.current = { overlay, onReport, ignore, classify, maxReports };\n\n React.useEffect(() => {\n // Everything stateful is owned by the effect so React controls its\n // lifetime. Strict Mode's setup → cleanup → setup then yields one live\n // controller, fully torn down and fully rebuilt, and the messages React\n // already logged are replayed to it from the capture backlog.\n const controller = new InspectorController(optionsRef.current);\n controller.start();\n return () => controller.stop();\n }, []);\n\n return React.createElement(React.Fragment, null, children);\n}\n","// NOTE: the `'use client'` directive for this entry is injected into the built\n// output by scripts/postbuild-use-client.mjs (esbuild strips source-level module\n// directives when bundling). This entry only exports client components.\nimport * as React from 'react';\nimport { InspectorController, type InspectorOptions } from './controller';\nimport { InspectorImpl, type HydrationInspectorProps } from './inspector';\n\nfunction PassThrough(props: {\n children?: React.ReactNode;\n}): React.ReactElement {\n return React.createElement(React.Fragment, null, props.children);\n}\n\n// The process.env.NODE_ENV checks are inline (not hoisted to a variable) so\n// production bundlers fold them and tree-shake the dev-only implementation.\nexport const HydrationInspector: (\n props: HydrationInspectorProps,\n) => React.ReactElement =\n process.env.NODE_ENV !== 'production' ? InspectorImpl : PassThrough;\n\nexport interface HydrationInspectorHandle {\n onRecoverableError: (\n error: unknown,\n info?: { componentStack?: string },\n ) => void;\n Provider: (props: { children?: React.ReactNode }) => React.ReactElement;\n}\n\nexport function createHydrationInspector(\n options: InspectorOptions = {},\n): HydrationInspectorHandle {\n if (process.env.NODE_ENV === 'production') {\n return {\n onRecoverableError: () => {},\n Provider: PassThrough,\n };\n }\n\n const controller = new InspectorController(options);\n controller.start();\n\n function Provider(props: { children?: React.ReactNode }): React.ReactElement {\n React.useEffect(() => {\n // The controller is started eagerly above, because the console has to be\n // intercepted before `hydrateRoot` runs. Strict Mode then plays this\n // effect setup → cleanup → setup, so a Provider that only stopped on\n // cleanup left the inspector dead for the rest of the session. `start()`\n // is idempotent and the controller is restartable, so re-starting here\n // yields exactly one live inspector either way.\n controller.start();\n return () => controller.stop();\n }, []);\n return React.createElement(React.Fragment, null, props.children);\n }\n\n return {\n onRecoverableError: controller.onRecoverableError,\n Provider,\n };\n}\n\nexport type { HydrationInspectorProps } from './inspector';\nexport type { InspectorOptions } from './controller';\nexport type { OverlayOptions } from './overlay';\nexport type {\n Cause,\n Classifier,\n DetectionContext,\n Divergence,\n HydrationCauseCategory,\n HydrationReport,\n} from '../core/types';\n"]}
|
|
@@ -9,9 +9,17 @@ function readSnapshot() {
|
|
|
9
9
|
if (typeof window === "undefined") return void 0;
|
|
10
10
|
return window[SNAPSHOT_KEY];
|
|
11
11
|
}
|
|
12
|
+
var resolved = /* @__PURE__ */ new WeakMap();
|
|
12
13
|
function getServerHtmlForRoot(root) {
|
|
13
14
|
const snapshot = readSnapshot();
|
|
14
15
|
if (!snapshot) return void 0;
|
|
16
|
+
const cached = resolved.get(root);
|
|
17
|
+
if (cached && cached.snapshot === snapshot) return cached.html;
|
|
18
|
+
const html = resolveServerHtml(snapshot, root);
|
|
19
|
+
resolved.set(root, { snapshot, html });
|
|
20
|
+
return html;
|
|
21
|
+
}
|
|
22
|
+
function resolveServerHtml(snapshot, root) {
|
|
15
23
|
for (const selector of Object.keys(snapshot.roots)) {
|
|
16
24
|
try {
|
|
17
25
|
if (root.matches(selector) || root === document.querySelector(selector)) {
|
|
@@ -20,8 +28,42 @@ function getServerHtmlForRoot(root) {
|
|
|
20
28
|
} catch {
|
|
21
29
|
}
|
|
22
30
|
}
|
|
31
|
+
return findNestedServerHtml(snapshot, root);
|
|
32
|
+
}
|
|
33
|
+
function findNestedServerHtml(snapshot, root) {
|
|
34
|
+
if (!root.id) return void 0;
|
|
35
|
+
const idSelector = `#${escapeId(root.id)}`;
|
|
36
|
+
for (const selector of Object.keys(snapshot.roots)) {
|
|
37
|
+
let container = null;
|
|
38
|
+
try {
|
|
39
|
+
container = document.querySelector(selector);
|
|
40
|
+
} catch {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (!container || container === root || !container.contains(root)) continue;
|
|
44
|
+
const html = snapshot.roots[selector];
|
|
45
|
+
if (html == null) continue;
|
|
46
|
+
const parsed = parseInert(html, container.tagName);
|
|
47
|
+
let match = null;
|
|
48
|
+
try {
|
|
49
|
+
match = parsed.querySelector(idSelector);
|
|
50
|
+
} catch {
|
|
51
|
+
match = null;
|
|
52
|
+
}
|
|
53
|
+
if (match) return match.innerHTML;
|
|
54
|
+
}
|
|
23
55
|
return void 0;
|
|
24
56
|
}
|
|
57
|
+
function escapeId(id) {
|
|
58
|
+
const cssEscape = globalThis.CSS?.escape;
|
|
59
|
+
return typeof cssEscape === "function" ? cssEscape(id) : id.replace(/[^\w-]/g, "\\$&");
|
|
60
|
+
}
|
|
61
|
+
function parseInert(html, tagName) {
|
|
62
|
+
const doc = document.implementation.createHTMLDocument("");
|
|
63
|
+
const container = doc.createElement(tagName || "div");
|
|
64
|
+
container.innerHTML = html;
|
|
65
|
+
return container;
|
|
66
|
+
}
|
|
25
67
|
function captureSnapshotNow(selectors = DEFAULT_SNAPSHOT_SELECTORS) {
|
|
26
68
|
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
27
69
|
return void 0;
|
|
@@ -38,5 +80,5 @@ function captureSnapshotNow(selectors = DEFAULT_SNAPSHOT_SELECTORS) {
|
|
|
38
80
|
}
|
|
39
81
|
|
|
40
82
|
export { DEFAULT_SNAPSHOT_SELECTORS, SNAPSHOT_KEY, captureSnapshotNow, getServerHtmlForRoot, getSnapshotScriptSource, readSnapshot };
|
|
41
|
-
//# sourceMappingURL=chunk-
|
|
42
|
-
//# sourceMappingURL=chunk-
|
|
83
|
+
//# sourceMappingURL=chunk-XIM33ZGB.js.map
|
|
84
|
+
//# sourceMappingURL=chunk-XIM33ZGB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/snapshot.ts"],"names":[],"mappings":"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","file":"chunk-XIM33ZGB.js","sourcesContent":["export const DEFAULT_SNAPSHOT_SELECTORS = ['#root', '#__next', 'body'];\n\nexport const SNAPSHOT_KEY = '__WHY_HYDRATION_SNAPSHOT__';\n\nexport interface Snapshot {\n version: 1;\n capturedAt: number;\n roots: Record<string, string>;\n}\n\ndeclare global {\n interface Window {\n [SNAPSHOT_KEY]?: Snapshot;\n }\n}\n\nexport function getSnapshotScriptSource(\n selectors: readonly string[] = DEFAULT_SNAPSHOT_SELECTORS,\n): string {\n const serialized = JSON.stringify(selectors).replace(/</g, '\\\\u003c');\n return `(function(){var K=${JSON.stringify(SNAPSHOT_KEY)};if(typeof window===\"undefined\"||window[K])return;var S=${serialized};function cap(){if(window[K])return;var r={};for(var i=0;i<S.length;i++){var el=document.querySelector(S[i]);if(el)r[S[i]]=el.innerHTML;}window[K]={version:1,capturedAt:Date.now(),roots:r};}if(document.readyState!==\"loading\"){cap();}else{document.addEventListener(\"readystatechange\",function(){if(document.readyState===\"interactive\")cap();});document.addEventListener(\"DOMContentLoaded\",cap);}})();`;\n}\n\nexport function readSnapshot(): Snapshot | undefined {\n if (typeof window === 'undefined') return undefined;\n return window[SNAPSHOT_KEY];\n}\n\n/**\n * Resolving a root can require parsing the entire captured page (see\n * `findNestedServerHtml`), and the settling window asks the same question once\n * per pass. The snapshot is written once and never mutated, so the answer is\n * cached per root element and keyed on snapshot identity — a replaced snapshot\n * invalidates it. A WeakMap keeps detached roots collectable.\n */\nconst resolved = new WeakMap<\n Element,\n { snapshot: Snapshot; html: string | undefined }\n>();\n\nexport function getServerHtmlForRoot(root: Element): string | undefined {\n const snapshot = readSnapshot();\n if (!snapshot) return undefined;\n const cached = resolved.get(root);\n if (cached && cached.snapshot === snapshot) return cached.html;\n const html = resolveServerHtml(snapshot, root);\n resolved.set(root, { snapshot, html });\n return html;\n}\n\nfunction resolveServerHtml(\n snapshot: Snapshot,\n root: Element,\n): string | undefined {\n for (const selector of Object.keys(snapshot.roots)) {\n try {\n if (root.matches(selector) || root === document.querySelector(selector)) {\n return snapshot.roots[selector];\n }\n } catch {\n /* invalid selector */\n }\n }\n return findNestedServerHtml(snapshot, root);\n}\n\n/**\n * A root the caller asked for (`roots: ['#app']`) may sit *inside* a captured\n * root (`body`) instead of being one itself, because the snapshot selectors are\n * chosen on the server and the inspected roots on the client. Recover its\n * server HTML by locating the same element by id inside the captured markup, so\n * a custom `roots` option still works against the default snapshot selectors.\n */\nfunction findNestedServerHtml(\n snapshot: Snapshot,\n root: Element,\n): string | undefined {\n if (!root.id) return undefined;\n const idSelector = `#${escapeId(root.id)}`;\n for (const selector of Object.keys(snapshot.roots)) {\n let container: Element | null = null;\n try {\n container = document.querySelector(selector);\n } catch {\n continue; // invalid selector\n }\n if (!container || container === root || !container.contains(root)) continue;\n const html = snapshot.roots[selector];\n if (html == null) continue;\n const parsed = parseInert(html, container.tagName);\n let match: Element | null = null;\n try {\n match = parsed.querySelector(idSelector);\n } catch {\n match = null;\n }\n if (match) return match.innerHTML;\n }\n return undefined;\n}\n\nfunction escapeId(id: string): string {\n const cssEscape = (globalThis as { CSS?: { escape?(value: string): string } })\n .CSS?.escape;\n return typeof cssEscape === 'function'\n ? cssEscape(id)\n : id.replace(/[^\\w-]/g, '\\\\$&');\n}\n\n// Kept local rather than shared with the diff engine: this module is also\n// reached from the server-rendered `next/script` entry, which must not pull the\n// dev-only diff implementation into its bundle.\nfunction parseInert(html: string, tagName: string): Element {\n const doc = document.implementation.createHTMLDocument('');\n const container = doc.createElement(tagName || 'div');\n container.innerHTML = html;\n return container;\n}\n\nexport function captureSnapshotNow(\n selectors: readonly string[] = DEFAULT_SNAPSHOT_SELECTORS,\n): Snapshot | undefined {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return undefined;\n }\n if (window[SNAPSHOT_KEY]) return window[SNAPSHOT_KEY];\n const roots: Record<string, string> = {};\n for (const selector of selectors) {\n const el = document.querySelector(selector);\n if (el) roots[selector] = el.innerHTML;\n }\n const snapshot: Snapshot = { version: 1, capturedAt: Date.now(), roots };\n window[SNAPSHOT_KEY] = snapshot;\n return snapshot;\n}\n"]}
|