rerender-lens 0.3.0 → 0.5.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/CHANGELOG.md +118 -0
- package/README.md +192 -353
- package/dist/{budget-COBu7jBU.d.cts → budget-BnJlYwrV.d.ts} +20 -10
- package/dist/{budget-LkNjGtRc.d.ts → budget-CRswn-nC.d.cts} +20 -10
- package/dist/cli.cjs +248 -31
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +248 -31
- package/dist/cli.js.map +1 -1
- package/dist/{devtools-BHGUUo-p.d.ts → devtools-BYWat7nQ.d.ts} +17 -3
- package/dist/{devtools-DmhWiWcN.d.cts → devtools-DJi_6AfJ.d.cts} +17 -3
- package/dist/index.cjs +635 -109
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +131 -8
- package/dist/index.d.ts +131 -8
- package/dist/index.js +620 -110
- package/dist/index.js.map +1 -1
- package/dist/jest-setup.cjs +1673 -0
- package/dist/jest-setup.cjs.map +1 -0
- package/dist/jest-setup.d.cts +8 -0
- package/dist/jest-setup.d.ts +8 -0
- package/dist/jest-setup.js +1671 -0
- package/dist/jest-setup.js.map +1 -0
- package/dist/jest.cjs +1760 -0
- package/dist/jest.cjs.map +1 -0
- package/dist/jest.d.cts +23 -0
- package/dist/jest.d.ts +23 -0
- package/dist/jest.js +1751 -0
- package/dist/jest.js.map +1 -0
- package/dist/{notifiers-BjjGSHpp.d.ts → notifiers-DwKlvv4H.d.cts} +8 -4
- package/dist/{notifiers-BGQtWKfX.d.cts → notifiers-FNzKHs0a.d.ts} +8 -4
- package/dist/playwright.cjs +235 -30
- package/dist/playwright.cjs.map +1 -1
- package/dist/playwright.d.cts +8 -6
- package/dist/playwright.d.ts +8 -6
- package/dist/playwright.js +235 -31
- package/dist/playwright.js.map +1 -1
- package/dist/relay.cjs +10 -2
- package/dist/relay.cjs.map +1 -1
- package/dist/relay.js +10 -2
- package/dist/relay.js.map +1 -1
- package/dist/rerender-lens.iife.js +1100 -337
- package/dist/runner-report-B8Sc3FZO.d.cts +46 -0
- package/dist/runner-report-CW8X5RwK.d.ts +46 -0
- package/dist/setup.cjs +308 -95
- package/dist/setup.cjs.map +1 -1
- package/dist/setup.js +308 -95
- package/dist/setup.js.map +1 -1
- package/dist/{types-BzUEVkxJ.d.cts → types-DW5-N2XH.d.cts} +55 -2
- package/dist/{types-BzUEVkxJ.d.ts → types-DW5-N2XH.d.ts} +55 -2
- package/dist/vite.d.cts +1 -1
- package/dist/vite.d.ts +1 -1
- package/dist/vitest-setup.cjs +452 -87
- package/dist/vitest-setup.cjs.map +1 -1
- package/dist/vitest-setup.d.cts +4 -4
- package/dist/vitest-setup.d.ts +4 -4
- package/dist/vitest-setup.js +452 -87
- package/dist/vitest-setup.js.map +1 -1
- package/dist/vitest.cjs +515 -123
- package/dist/vitest.cjs.map +1 -1
- package/dist/vitest.d.cts +21 -39
- package/dist/vitest.d.ts +21 -39
- package/dist/vitest.js +516 -124
- package/dist/vitest.js.map +1 -1
- package/package.json +41 -5
- package/panel/panel.css +1 -34
- package/panel/panel.js +865 -713
|
@@ -1,10 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/* rerender-lens 0.5.0 — rerender-lens.core.js: types, version, diff, report, state, overlay. Built by scripts/build-vendor.mjs; do not edit. */
|
|
2
|
+
(() => {
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __export = (target, all) => {
|
|
5
|
+
for (var name in all)
|
|
6
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
7
|
+
};
|
|
3
8
|
|
|
4
9
|
// src/types.ts
|
|
10
|
+
var types_exports = {};
|
|
11
|
+
__export(types_exports, {
|
|
12
|
+
MARKER: () => MARKER
|
|
13
|
+
});
|
|
5
14
|
var MARKER = "rerenderLens";
|
|
6
15
|
|
|
16
|
+
// src/version.ts
|
|
17
|
+
var version_exports = {};
|
|
18
|
+
__export(version_exports, {
|
|
19
|
+
VERSION: () => VERSION
|
|
20
|
+
});
|
|
21
|
+
var VERSION = true ? "0.5.0" : "dev";
|
|
22
|
+
|
|
7
23
|
// src/diff.ts
|
|
24
|
+
var diff_exports = {};
|
|
25
|
+
__export(diff_exports, {
|
|
26
|
+
AVOIDABLE_KINDS: () => AVOIDABLE_KINDS,
|
|
27
|
+
DEFAULT_DIFF_BUDGET: () => DEFAULT_DIFF_BUDGET,
|
|
28
|
+
beginDiffScope: () => beginDiffScope,
|
|
29
|
+
classify: () => classify,
|
|
30
|
+
deepEqual: () => deepEqual,
|
|
31
|
+
diffBudgetExhausted: () => diffBudgetExhausted,
|
|
32
|
+
diffLeaves: () => diffLeaves,
|
|
33
|
+
diffRecords: () => diffRecords,
|
|
34
|
+
firstDifferentPath: () => firstDifferentPath,
|
|
35
|
+
isReactElement: () => isReactElement
|
|
36
|
+
});
|
|
8
37
|
var REACT_ELEMENT = /* @__PURE__ */ Symbol.for("react.element");
|
|
9
38
|
var REACT_TRANSITIONAL_ELEMENT = /* @__PURE__ */ Symbol.for("react.transitional.element");
|
|
10
39
|
function isReactElement(v) {
|
|
@@ -27,10 +56,49 @@ var RerenderLens = (function (exports) {
|
|
|
27
56
|
set.add(b);
|
|
28
57
|
return false;
|
|
29
58
|
}
|
|
59
|
+
var scope = null;
|
|
60
|
+
var DEFAULT_DIFF_BUDGET = 5e4;
|
|
61
|
+
function beginDiffScope(budget = 2e5) {
|
|
62
|
+
const previous = scope;
|
|
63
|
+
scope = { cache: /* @__PURE__ */ new WeakMap(), remaining: budget, exhausted: false };
|
|
64
|
+
return () => {
|
|
65
|
+
scope = previous;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function diffBudgetExhausted() {
|
|
69
|
+
return scope?.exhausted === true;
|
|
70
|
+
}
|
|
30
71
|
function deepEqual(a, b, seen = /* @__PURE__ */ new Map()) {
|
|
31
72
|
if (Object.is(a, b)) return true;
|
|
32
73
|
if (typeof a !== typeof b) return false;
|
|
33
74
|
if (typeof a !== "object" || a === null || b === null) return false;
|
|
75
|
+
if (!scope) {
|
|
76
|
+
const end = beginDiffScope(DEFAULT_DIFF_BUDGET);
|
|
77
|
+
try {
|
|
78
|
+
return deepEqual(a, b, seen);
|
|
79
|
+
} finally {
|
|
80
|
+
end();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const sc = scope;
|
|
84
|
+
const objA = a;
|
|
85
|
+
const objB = b;
|
|
86
|
+
const hit = sc.cache.get(objA)?.get(objB);
|
|
87
|
+
if (hit !== void 0) return hit;
|
|
88
|
+
if (--sc.remaining < 0) {
|
|
89
|
+
sc.exhausted = true;
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
const result = deepEqualObjects(objA, objB, seen);
|
|
93
|
+
let m = sc.cache.get(objA);
|
|
94
|
+
if (!m) {
|
|
95
|
+
m = /* @__PURE__ */ new WeakMap();
|
|
96
|
+
sc.cache.set(objA, m);
|
|
97
|
+
}
|
|
98
|
+
m.set(objB, result);
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
function deepEqualObjects(a, b, seen) {
|
|
34
102
|
const objA = a;
|
|
35
103
|
const objB = b;
|
|
36
104
|
if (remember(seen, objA, objB)) return true;
|
|
@@ -59,6 +127,10 @@ var RerenderLens = (function (exports) {
|
|
|
59
127
|
}
|
|
60
128
|
if (a instanceof Set) {
|
|
61
129
|
if (!(b instanceof Set) || a.size !== b.size) return false;
|
|
130
|
+
if (a.size > 50) {
|
|
131
|
+
for (const v of a) if (!b.has(v)) return false;
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
62
134
|
outer: for (const v of a) {
|
|
63
135
|
if (b.has(v)) continue;
|
|
64
136
|
for (const w of b) if (deepEqual(v, w, seen)) continue outer;
|
|
@@ -74,14 +146,16 @@ var RerenderLens = (function (exports) {
|
|
|
74
146
|
const ka = Object.keys(a);
|
|
75
147
|
const kb = Object.keys(b);
|
|
76
148
|
if (ka.length !== kb.length) return false;
|
|
149
|
+
const rb = b;
|
|
77
150
|
for (const k of ka) {
|
|
78
151
|
if (!Object.prototype.hasOwnProperty.call(b, k)) return false;
|
|
79
|
-
if (!deepEqual(a[k],
|
|
152
|
+
if (!deepEqual(a[k], rb[k], seen)) return false;
|
|
80
153
|
}
|
|
81
154
|
return true;
|
|
82
155
|
}
|
|
83
156
|
return false;
|
|
84
157
|
}
|
|
158
|
+
var AVOIDABLE_KINDS = /* @__PURE__ */ new Set(["deep-equal", "function", "element"]);
|
|
85
159
|
function classify(prev, next) {
|
|
86
160
|
if (typeof prev === "function" && typeof next === "function") {
|
|
87
161
|
return prev.name === next.name && prev.toString() === next.toString() ? "function" : "different";
|
|
@@ -118,33 +192,60 @@ var RerenderLens = (function (exports) {
|
|
|
118
192
|
if (Object.is(a, b)) continue;
|
|
119
193
|
const kind = classify(a, b);
|
|
120
194
|
if (kind === "different") {
|
|
121
|
-
changes.push({ path: firstDifferentPath(a, b, path), kind, prev: a, next: b });
|
|
195
|
+
changes.push({ path: diffBudgetExhausted() ? path : firstDifferentPath(a, b, path) ?? path, kind, prev: a, next: b });
|
|
122
196
|
} else {
|
|
123
197
|
changes.push({ path, kind, prev: a, next: b });
|
|
124
198
|
}
|
|
125
199
|
}
|
|
126
200
|
return changes;
|
|
127
201
|
}
|
|
128
|
-
function firstDifferentPath(a, b, path, depth = 0) {
|
|
129
|
-
if (depth > 8) return path;
|
|
202
|
+
function firstDifferentPath(a, b, path = "", depth = 0) {
|
|
203
|
+
if (depth > 8) return path || "(value)";
|
|
130
204
|
if (Array.isArray(a) && Array.isArray(b)) {
|
|
131
|
-
if (a.length !== b.length) return `${path}.length
|
|
205
|
+
if (a.length !== b.length) return path ? `${path}.length` : "length";
|
|
132
206
|
for (let i = 0; i < a.length; i++) {
|
|
133
207
|
if (!deepEqual(a[i], b[i])) return firstDifferentPath(a[i], b[i], joinPath(path, i), depth + 1);
|
|
134
208
|
}
|
|
135
|
-
return
|
|
209
|
+
return null;
|
|
136
210
|
}
|
|
137
211
|
if (isPlainObject(a) && isPlainObject(b)) {
|
|
138
212
|
const keys = /* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)]);
|
|
139
213
|
for (const k of keys) {
|
|
140
214
|
if (!deepEqual(a[k], b[k])) return firstDifferentPath(a[k], b[k], joinPath(path, k), depth + 1);
|
|
141
215
|
}
|
|
142
|
-
return
|
|
216
|
+
return null;
|
|
143
217
|
}
|
|
144
|
-
return path;
|
|
218
|
+
return deepEqual(a, b) ? null : path || "(value)";
|
|
219
|
+
}
|
|
220
|
+
function diffLeaves(a, b, limit = 20, path = "", out = []) {
|
|
221
|
+
if (out.length >= limit || Object.is(a, b)) return out;
|
|
222
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
223
|
+
const n = Math.max(a.length, b.length);
|
|
224
|
+
for (let i = 0; i < n && out.length < limit; i++) diffLeaves(a[i], b[i], limit, joinPath(path, i), out);
|
|
225
|
+
return out;
|
|
226
|
+
}
|
|
227
|
+
if (isPlainObject(a) && isPlainObject(b)) {
|
|
228
|
+
for (const k of /* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)])) {
|
|
229
|
+
if (out.length >= limit) break;
|
|
230
|
+
diffLeaves(a[k], b[k], limit, joinPath(path, k), out);
|
|
231
|
+
}
|
|
232
|
+
return out;
|
|
233
|
+
}
|
|
234
|
+
if (!deepEqual(a, b)) out.push({ path: path || "(value)", prev: a, next: b });
|
|
235
|
+
return out;
|
|
145
236
|
}
|
|
146
237
|
|
|
147
238
|
// src/report.ts
|
|
239
|
+
var report_exports = {};
|
|
240
|
+
__export(report_exports, {
|
|
241
|
+
KIND_LABEL: () => KIND_LABEL,
|
|
242
|
+
buildReport: () => buildReport,
|
|
243
|
+
fixFor: () => fixFor,
|
|
244
|
+
hookLabel: () => hookLabel,
|
|
245
|
+
printReport: () => printReport,
|
|
246
|
+
storeAdvice: () => storeAdvice,
|
|
247
|
+
summarize: () => summarize
|
|
248
|
+
});
|
|
148
249
|
var now = () => typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
149
250
|
var hookLabel = (c) => c.custom && c.custom.length ? `${c.custom.join(" \u203A ")} \u203A ${c.hook}#${c.index}` : `${c.hook} #${c.index}`;
|
|
150
251
|
function storeAdvice(custom) {
|
|
@@ -159,10 +260,12 @@ var RerenderLens = (function (exports) {
|
|
|
159
260
|
}
|
|
160
261
|
var isGenuine = (c) => c.kind === "different" || c.kind === "added" || c.kind === "removed";
|
|
161
262
|
var isChildren = (change) => change.path === "children";
|
|
263
|
+
var isRefObject = (change) => change.path === "ref" && change.kind === "deep-equal";
|
|
162
264
|
function fixFor(change) {
|
|
163
265
|
if (isChildren(change) && (change.kind === "element" || change.kind === "deep-equal")) {
|
|
164
266
|
return `lift the children out of the parent's render: memoize them with useMemo, hoist static elements to module scope, or render them from a component that does not re-render`;
|
|
165
267
|
}
|
|
268
|
+
if (isRefObject(change)) return `create the ref once with useRef (or createRef outside the render) and pass the same object every time`;
|
|
166
269
|
switch (change.kind) {
|
|
167
270
|
case "function":
|
|
168
271
|
return `wrap it in useCallback (or hoist it out of the parent's render)`;
|
|
@@ -178,6 +281,7 @@ var RerenderLens = (function (exports) {
|
|
|
178
281
|
if (isChildren(change) && (change.kind === "element" || change.kind === "deep-equal")) {
|
|
179
282
|
return `children are new React elements with the same types and props on every render of the parent`;
|
|
180
283
|
}
|
|
284
|
+
if (isRefObject(change)) return `prop "ref" is a new ref object on every render (React re-attaches it each time)`;
|
|
181
285
|
switch (change.kind) {
|
|
182
286
|
case "deep-equal":
|
|
183
287
|
return `prop "${change.path}" is a new reference but deep-equal to the previous value`;
|
|
@@ -205,11 +309,21 @@ var RerenderLens = (function (exports) {
|
|
|
205
309
|
if (causes.length === 0) trigger = "parent";
|
|
206
310
|
else if (causes.length === 1) trigger = causes[0];
|
|
207
311
|
else trigger = "mixed";
|
|
208
|
-
const
|
|
312
|
+
const nothingChanged = input.propChanges.length === 0 && stateChanges.length === 0 && hookChanges.length === 0;
|
|
313
|
+
const cacheHit = input.compiled === true && trigger === "parent" && input.propChanges.length === 0;
|
|
314
|
+
const revealed = input.revealed === true && trigger === "parent";
|
|
315
|
+
const avoidable = trigger === "parent" && !cacheHit && !revealed;
|
|
209
316
|
const reasons = [];
|
|
210
|
-
|
|
317
|
+
const memoFix = input.classComponent ? `Make "${input.component}" extend PureComponent (or implement shouldComponentUpdate)` : `Wrap "${input.component}" in React.memo (or extend PureComponent)`;
|
|
318
|
+
if (cacheHit) {
|
|
319
|
+
reasons.push(`compiled by React Compiler: its output is memoized and the inputs did not change, so this render is cheap; nothing to fix.`);
|
|
320
|
+
} else if (revealed) {
|
|
321
|
+
reasons.push(
|
|
322
|
+
`re-rendered because the Suspense boundary above it switched from its fallback to content: React re-renders the content it kept hidden while the fallback was shown. A one-off; nothing to fix.`
|
|
323
|
+
);
|
|
324
|
+
} else if (avoidable && nothingChanged) {
|
|
211
325
|
const who = input.parent ? `<${input.parent.name}> re-rendered (${describeTrigger(input.parent.trigger)})` : "its parent re-rendered";
|
|
212
|
-
reasons.push(`re-rendered with identical props because ${who}.
|
|
326
|
+
reasons.push(`re-rendered with identical props because ${who}. ${memoFix}.`);
|
|
213
327
|
} else if (avoidable && input.parent) {
|
|
214
328
|
reasons.push(`caused by <${input.parent.name}> re-rendering (${describeTrigger(input.parent.trigger)}).`);
|
|
215
329
|
}
|
|
@@ -218,9 +332,9 @@ var RerenderLens = (function (exports) {
|
|
|
218
332
|
reasons.push(fix ? `${describe(c)}: ${fix}.` : `${describe(c)}.`);
|
|
219
333
|
}
|
|
220
334
|
const memoized = input.memoized !== false;
|
|
221
|
-
if (avoidable && !memoized && input.propChanges.length > 0) {
|
|
335
|
+
if (avoidable && !memoized && !input.compiled && input.propChanges.length > 0) {
|
|
222
336
|
reasons.push(
|
|
223
|
-
`"${input.component}" is not memoized, so fixing the props alone will not stop this re-render: also wrap it in React.memo (or extend PureComponent).`
|
|
337
|
+
`"${input.component}" is not memoized, so fixing the props alone will not stop this re-render: also ${input.classComponent ? "extend PureComponent (or implement shouldComponentUpdate)" : "wrap it in React.memo (or extend PureComponent)"}.`
|
|
224
338
|
);
|
|
225
339
|
}
|
|
226
340
|
for (const c of stateChanges) {
|
|
@@ -232,6 +346,8 @@ var RerenderLens = (function (exports) {
|
|
|
232
346
|
const where = c.provider && c.provider.component ? ` (provided by <${c.provider.component}>)` : "";
|
|
233
347
|
const keys = c.changedKeys && typeof c.totalKeys === "number" && c.changedKeys.length > 0 && c.changedKeys.length < c.totalKeys ? `: only ${c.changedKeys.map((k) => `"${k}"`).join(", ")} of ${c.totalKeys} keys changed, yet every consumer re-renders. Split the context or memoize the slices consumers read` : "";
|
|
234
348
|
reasons.push(`${c.path} changed${where}${keys}.`);
|
|
349
|
+
} else if (c.hook === "useDeferredValue" && isGenuine(c)) {
|
|
350
|
+
reasons.push(`${hookLabel(c)} caught up with its latest value: this is the deferred second render React schedules after the urgent one; nothing to fix.`);
|
|
235
351
|
} else if (isGenuine(c)) reasons.push(`${hookLabel(c)} changed.`);
|
|
236
352
|
else if (isStateHook(c))
|
|
237
353
|
reasons.push(`${hookLabel(c)} was set to a value deep-equal to the current one (new reference, same contents): reuse the existing object or bail out before calling the setter.`);
|
|
@@ -262,6 +378,7 @@ var RerenderLens = (function (exports) {
|
|
|
262
378
|
reasons,
|
|
263
379
|
time: now()
|
|
264
380
|
};
|
|
381
|
+
if (input.compiled) report.compiled = true;
|
|
265
382
|
if (input.selfDuration !== void 0) report.selfDuration = input.selfDuration;
|
|
266
383
|
if (input.treeDuration !== void 0) report.treeDuration = input.treeDuration;
|
|
267
384
|
if (input.commitPriority) report.commitPriority = input.commitPriority;
|
|
@@ -298,13 +415,13 @@ var RerenderLens = (function (exports) {
|
|
|
298
415
|
removed: "removed"
|
|
299
416
|
};
|
|
300
417
|
function summarize(report) {
|
|
301
|
-
const
|
|
302
|
-
for (const c of [...report.propChanges, ...report.stateChanges, ...report.hookChanges]) {
|
|
303
|
-
|
|
418
|
+
const counts = /* @__PURE__ */ new Map();
|
|
419
|
+
for (const c of [...report.propChanges || [], ...report.stateChanges || [], ...report.hookChanges || []]) {
|
|
420
|
+
counts.set(c.kind, (counts.get(c.kind) ?? 0) + 1);
|
|
304
421
|
}
|
|
305
|
-
const
|
|
306
|
-
if (
|
|
307
|
-
return
|
|
422
|
+
const parts2 = [...counts].map(([kind, n]) => `${n} ${KIND_LABEL[kind] || kind}`);
|
|
423
|
+
if (parts2.length === 0) parts2.push("no changes");
|
|
424
|
+
return parts2.join(", ");
|
|
308
425
|
}
|
|
309
426
|
function printReport(report, options) {
|
|
310
427
|
const c = options.console ?? console;
|
|
@@ -324,12 +441,18 @@ var RerenderLens = (function (exports) {
|
|
|
324
441
|
}
|
|
325
442
|
|
|
326
443
|
// src/state.ts
|
|
444
|
+
var state_exports = {};
|
|
445
|
+
__export(state_exports, {
|
|
446
|
+
dispatch: () => dispatch,
|
|
447
|
+
getState: () => getState,
|
|
448
|
+
warnOnce: () => warnOnce
|
|
449
|
+
});
|
|
327
450
|
var KEY = /* @__PURE__ */ Symbol.for("rerender-lens.state");
|
|
328
451
|
function getState() {
|
|
329
452
|
const g = globalThis;
|
|
330
453
|
let s = g[KEY];
|
|
331
454
|
if (!s) {
|
|
332
|
-
s = { options: {}, enabled: false, printed: /* @__PURE__ */ new Map(), detach: null, nextInstanceId: 1, nextCommitId: 1, warnedOnce: /* @__PURE__ */ new Set(), scheduled: 0, commits: 0, overheadMs: 0, maxCommitMs: 0 };
|
|
455
|
+
s = { options: {}, enabled: false, printed: /* @__PURE__ */ new Map(), detach: null, nextInstanceId: 1, nextCommitId: 1, warnedOnce: /* @__PURE__ */ new Set(), scheduled: 0, commits: 0, overheadMs: 0, maxCommitMs: 0, truncated: 0 };
|
|
333
456
|
g[KEY] = s;
|
|
334
457
|
}
|
|
335
458
|
return s;
|
|
@@ -342,7 +465,7 @@ var RerenderLens = (function (exports) {
|
|
|
342
465
|
}
|
|
343
466
|
function dispatch(report, override) {
|
|
344
467
|
const s = getState();
|
|
345
|
-
const options = s.options;
|
|
468
|
+
const options = override ? { ...s.options, ...override } : s.options;
|
|
346
469
|
if (!options.silent && (report.avoidable || options.logAll)) {
|
|
347
470
|
const max = options.maxReportsPerComponent ?? 0;
|
|
348
471
|
const n = (s.printed.get(report.component) ?? 0) + 1;
|
|
@@ -359,12 +482,348 @@ var RerenderLens = (function (exports) {
|
|
|
359
482
|
try {
|
|
360
483
|
options.notifier(report);
|
|
361
484
|
} catch (err) {
|
|
362
|
-
(
|
|
485
|
+
warnOnce("notifier", `notifier threw: ${String(err)}`);
|
|
363
486
|
}
|
|
364
487
|
}
|
|
365
488
|
}
|
|
366
489
|
|
|
490
|
+
// src/overlay.ts
|
|
491
|
+
var overlay_exports = {};
|
|
492
|
+
__export(overlay_exports, {
|
|
493
|
+
clearHighlight: () => clearHighlight,
|
|
494
|
+
destroyOverlay: () => destroyOverlay,
|
|
495
|
+
flash: () => flash,
|
|
496
|
+
highlight: () => highlight
|
|
497
|
+
});
|
|
498
|
+
var ROOT_ID = "rerender-lens-overlay";
|
|
499
|
+
var layer = null;
|
|
500
|
+
function ensureLayer() {
|
|
501
|
+
if (typeof document === "undefined" || !document.body) return null;
|
|
502
|
+
if (layer && layer.root.isConnected) return layer;
|
|
503
|
+
let root = document.getElementById(ROOT_ID);
|
|
504
|
+
if (!root) {
|
|
505
|
+
root = document.createElement("div");
|
|
506
|
+
root.id = ROOT_ID;
|
|
507
|
+
root.setAttribute("aria-hidden", "true");
|
|
508
|
+
Object.assign(root.style, {
|
|
509
|
+
position: "fixed",
|
|
510
|
+
inset: "0",
|
|
511
|
+
pointerEvents: "none",
|
|
512
|
+
zIndex: "2147483647",
|
|
513
|
+
overflow: "visible"
|
|
514
|
+
});
|
|
515
|
+
document.body.appendChild(root);
|
|
516
|
+
}
|
|
517
|
+
layer = { root, sticky: [] };
|
|
518
|
+
return layer;
|
|
519
|
+
}
|
|
520
|
+
function box(rect, color, fill, label) {
|
|
521
|
+
const b = document.createElement("div");
|
|
522
|
+
Object.assign(b.style, {
|
|
523
|
+
position: "absolute",
|
|
524
|
+
left: `${rect.left}px`,
|
|
525
|
+
top: `${rect.top}px`,
|
|
526
|
+
width: `${Math.max(rect.width, 2)}px`,
|
|
527
|
+
height: `${Math.max(rect.height, 2)}px`,
|
|
528
|
+
boxSizing: "border-box",
|
|
529
|
+
border: `2px solid ${color}`,
|
|
530
|
+
background: fill,
|
|
531
|
+
borderRadius: "2px"
|
|
532
|
+
});
|
|
533
|
+
if (label) {
|
|
534
|
+
const tag = document.createElement("span");
|
|
535
|
+
tag.textContent = label;
|
|
536
|
+
Object.assign(tag.style, {
|
|
537
|
+
position: "absolute",
|
|
538
|
+
left: "-2px",
|
|
539
|
+
top: rect.top > 20 ? "-20px" : "100%",
|
|
540
|
+
font: "11px/16px system-ui, sans-serif",
|
|
541
|
+
color: "#fff",
|
|
542
|
+
background: color,
|
|
543
|
+
padding: "1px 5px",
|
|
544
|
+
borderRadius: "2px",
|
|
545
|
+
whiteSpace: "nowrap"
|
|
546
|
+
});
|
|
547
|
+
b.appendChild(tag);
|
|
548
|
+
}
|
|
549
|
+
return b;
|
|
550
|
+
}
|
|
551
|
+
function highlight(target) {
|
|
552
|
+
const l = ensureLayer();
|
|
553
|
+
if (!l) return;
|
|
554
|
+
for (const s of l.sticky) s.remove();
|
|
555
|
+
l.sticky = [];
|
|
556
|
+
if (!target) return;
|
|
557
|
+
const frag = document.createDocumentFragment();
|
|
558
|
+
for (const rect of measure(target.nodes)) {
|
|
559
|
+
const b = box(rect, "#1a73e8", "rgba(26, 115, 232, 0.12)", target.label);
|
|
560
|
+
frag.appendChild(b);
|
|
561
|
+
l.sticky.push(b);
|
|
562
|
+
}
|
|
563
|
+
l.root.appendChild(frag);
|
|
564
|
+
}
|
|
565
|
+
var MAX_BOXES = 100;
|
|
566
|
+
function measure(nodes) {
|
|
567
|
+
const rects = [];
|
|
568
|
+
for (const node of nodes) {
|
|
569
|
+
if (rects.length >= MAX_BOXES) break;
|
|
570
|
+
const rect = node.getBoundingClientRect();
|
|
571
|
+
if (rect.width === 0 && rect.height === 0) continue;
|
|
572
|
+
rects.push(rect);
|
|
573
|
+
}
|
|
574
|
+
return rects;
|
|
575
|
+
}
|
|
576
|
+
function clearHighlight() {
|
|
577
|
+
highlight(null);
|
|
578
|
+
}
|
|
579
|
+
function flash(target, duration = 500) {
|
|
580
|
+
const l = ensureLayer();
|
|
581
|
+
if (!l) return;
|
|
582
|
+
const frag = document.createDocumentFragment();
|
|
583
|
+
const boxes = [];
|
|
584
|
+
for (const rect of measure(target.nodes)) {
|
|
585
|
+
const b = box(rect, "#d93025", "rgba(217, 48, 37, 0.15)");
|
|
586
|
+
b.style.transition = `opacity ${duration}ms ease-out`;
|
|
587
|
+
frag.appendChild(b);
|
|
588
|
+
boxes.push(b);
|
|
589
|
+
}
|
|
590
|
+
if (!boxes.length) return;
|
|
591
|
+
l.root.appendChild(frag);
|
|
592
|
+
requestAnimationFrame(() => {
|
|
593
|
+
for (const b of boxes) b.style.opacity = "0";
|
|
594
|
+
});
|
|
595
|
+
setTimeout(() => {
|
|
596
|
+
for (const b of boxes) b.remove();
|
|
597
|
+
}, duration + 50);
|
|
598
|
+
}
|
|
599
|
+
function destroyOverlay() {
|
|
600
|
+
if (layer) layer.root.remove();
|
|
601
|
+
layer = null;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// vendor-rerender-lens.core.js
|
|
605
|
+
var parts = globalThis.__RERENDER_LENS_PARTS__ = globalThis.__RERENDER_LENS_PARTS__ || {};
|
|
606
|
+
parts["types"] = types_exports;
|
|
607
|
+
parts["version"] = version_exports;
|
|
608
|
+
parts["diff"] = diff_exports;
|
|
609
|
+
parts["report"] = report_exports;
|
|
610
|
+
parts["state"] = state_exports;
|
|
611
|
+
parts["overlay"] = overlay_exports;
|
|
612
|
+
})();
|
|
613
|
+
|
|
614
|
+
;
|
|
615
|
+
/* rerender-lens 0.5.0 — rerender-lens.engine.js: fiber, tracker, hookNames. Built by scripts/build-vendor.mjs; do not edit. */
|
|
616
|
+
(() => {
|
|
617
|
+
var __create = Object.create;
|
|
618
|
+
var __defProp = Object.defineProperty;
|
|
619
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
620
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
621
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
622
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
623
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
624
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
625
|
+
};
|
|
626
|
+
var __export = (target, all) => {
|
|
627
|
+
for (var name in all)
|
|
628
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
629
|
+
};
|
|
630
|
+
var __copyProps = (to, from, except, desc) => {
|
|
631
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
632
|
+
for (let key of __getOwnPropNames(from))
|
|
633
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
634
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
635
|
+
}
|
|
636
|
+
return to;
|
|
637
|
+
};
|
|
638
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
639
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
640
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
641
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
642
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
643
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
644
|
+
mod
|
|
645
|
+
));
|
|
646
|
+
|
|
647
|
+
// rerender-lens-part:diff
|
|
648
|
+
var require_diff = __commonJS({
|
|
649
|
+
"rerender-lens-part:diff"(exports, module) {
|
|
650
|
+
var p = globalThis.__RERENDER_LENS_PARTS__;
|
|
651
|
+
if (!p || !p["diff"]) throw new Error("rerender-lens: load vendor/rerender-lens.core.js and vendor/rerender-lens.engine.js before vendor/rerender-lens.js");
|
|
652
|
+
module.exports = p["diff"];
|
|
653
|
+
}
|
|
654
|
+
});
|
|
655
|
+
|
|
656
|
+
// rerender-lens-part:report
|
|
657
|
+
var require_report = __commonJS({
|
|
658
|
+
"rerender-lens-part:report"(exports, module) {
|
|
659
|
+
var p = globalThis.__RERENDER_LENS_PARTS__;
|
|
660
|
+
if (!p || !p["report"]) throw new Error("rerender-lens: load vendor/rerender-lens.core.js and vendor/rerender-lens.engine.js before vendor/rerender-lens.js");
|
|
661
|
+
module.exports = p["report"];
|
|
662
|
+
}
|
|
663
|
+
});
|
|
664
|
+
|
|
665
|
+
// rerender-lens-part:state
|
|
666
|
+
var require_state = __commonJS({
|
|
667
|
+
"rerender-lens-part:state"(exports, module) {
|
|
668
|
+
var p = globalThis.__RERENDER_LENS_PARTS__;
|
|
669
|
+
if (!p || !p["state"]) throw new Error("rerender-lens: load vendor/rerender-lens.core.js and vendor/rerender-lens.engine.js before vendor/rerender-lens.js");
|
|
670
|
+
module.exports = p["state"];
|
|
671
|
+
}
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
// rerender-lens-part:types
|
|
675
|
+
var require_types = __commonJS({
|
|
676
|
+
"rerender-lens-part:types"(exports, module) {
|
|
677
|
+
var p = globalThis.__RERENDER_LENS_PARTS__;
|
|
678
|
+
if (!p || !p["types"]) throw new Error("rerender-lens: load vendor/rerender-lens.core.js and vendor/rerender-lens.engine.js before vendor/rerender-lens.js");
|
|
679
|
+
module.exports = p["types"];
|
|
680
|
+
}
|
|
681
|
+
});
|
|
682
|
+
|
|
683
|
+
// src/fiber.ts
|
|
684
|
+
var fiber_exports = {};
|
|
685
|
+
__export(fiber_exports, {
|
|
686
|
+
COMMIT_TIME_BUDGET_MS: () => COMMIT_TIME_BUDGET_MS,
|
|
687
|
+
MAX_REPORTS_PER_COMMIT: () => MAX_REPORTS_PER_COMMIT,
|
|
688
|
+
attach: () => attach,
|
|
689
|
+
durationsOf: () => durationsOf,
|
|
690
|
+
ensureDevtoolsHook: () => ensureDevtoolsHook,
|
|
691
|
+
fiberById: () => fiberById,
|
|
692
|
+
fiberForNode: () => fiberForNode,
|
|
693
|
+
fiberName: () => fiberName,
|
|
694
|
+
fiberType: () => fiberType,
|
|
695
|
+
findProvider: () => findProvider,
|
|
696
|
+
getDispatcherRef: () => getDispatcherRef,
|
|
697
|
+
getRenderers: () => getRenderers,
|
|
698
|
+
hostNodesOf: () => hostNodesOf,
|
|
699
|
+
instanceIdOf: () => instanceIdOf,
|
|
700
|
+
isCompiledFiber: () => isCompiledFiber,
|
|
701
|
+
isMemoizedFiber: () => isMemoizedFiber,
|
|
702
|
+
isProductionReact: () => isProductionReact,
|
|
703
|
+
nearestComponent: () => nearestComponent,
|
|
704
|
+
onCommit: () => onCommit,
|
|
705
|
+
parseStackLocation: () => parseStackLocation,
|
|
706
|
+
priorityLabel: () => priorityLabel,
|
|
707
|
+
snapshotContexts: () => snapshotContexts,
|
|
708
|
+
snapshotHooks: () => snapshotHooks,
|
|
709
|
+
sourceOf: () => sourceOf
|
|
710
|
+
});
|
|
711
|
+
var import_diff = __toESM(require_diff(), 1);
|
|
712
|
+
var import_report = __toESM(require_report(), 1);
|
|
713
|
+
var import_state2 = __toESM(require_state(), 1);
|
|
714
|
+
|
|
715
|
+
// src/tracker.ts
|
|
716
|
+
var tracker_exports = {};
|
|
717
|
+
__export(tracker_exports, {
|
|
718
|
+
configure: () => configure,
|
|
719
|
+
disable: () => disable,
|
|
720
|
+
getDisplayName: () => getDisplayName,
|
|
721
|
+
init: () => init,
|
|
722
|
+
isEnabled: () => isEnabled,
|
|
723
|
+
shouldTrack: () => shouldTrack,
|
|
724
|
+
track: () => track
|
|
725
|
+
});
|
|
726
|
+
var import_types = __toESM(require_types(), 1);
|
|
727
|
+
var import_state = __toESM(require_state(), 1);
|
|
728
|
+
var MEMO = /* @__PURE__ */ Symbol.for("react.memo");
|
|
729
|
+
var FORWARD_REF = /* @__PURE__ */ Symbol.for("react.forward_ref");
|
|
730
|
+
var isMemo = (t) => typeof t === "object" && t !== null && t.$$typeof === MEMO;
|
|
731
|
+
var isForwardRef = (t) => typeof t === "object" && t !== null && t.$$typeof === FORWARD_REF;
|
|
732
|
+
var isClass = (t) => typeof t === "function" && !!t.prototype?.isReactComponent;
|
|
733
|
+
var isPureClass = (t) => isClass(t) && !!t.prototype.isPureReactComponent;
|
|
734
|
+
var isComponentLike = (t) => typeof t === "function" || isMemo(t) || isForwardRef(t);
|
|
735
|
+
function getDisplayName(type) {
|
|
736
|
+
if (typeof type === "string") return type;
|
|
737
|
+
if (isMemo(type)) return type.displayName ?? getDisplayName(type.type);
|
|
738
|
+
if (isForwardRef(type)) return type.displayName ?? getDisplayName(type.render);
|
|
739
|
+
if (typeof type === "function") {
|
|
740
|
+
const t = type;
|
|
741
|
+
return t.displayName ?? (t.name || "Anonymous");
|
|
742
|
+
}
|
|
743
|
+
return "Anonymous";
|
|
744
|
+
}
|
|
745
|
+
function hasMarker(type) {
|
|
746
|
+
if (type === null || typeof type !== "function" && typeof type !== "object") return false;
|
|
747
|
+
if (type[import_types.MARKER] === true) return true;
|
|
748
|
+
if (isMemo(type)) return hasMarker(type.type);
|
|
749
|
+
if (isForwardRef(type)) return hasMarker(type.render);
|
|
750
|
+
return false;
|
|
751
|
+
}
|
|
752
|
+
function matches(m, name) {
|
|
753
|
+
if (typeof m === "string") return m === name;
|
|
754
|
+
if (m instanceof RegExp) return m.test(name);
|
|
755
|
+
return m(name);
|
|
756
|
+
}
|
|
757
|
+
function shouldTrack(type, o) {
|
|
758
|
+
if (!isComponentLike(type)) return false;
|
|
759
|
+
const name = getDisplayName(type);
|
|
760
|
+
if (o.exclude?.some((m) => matches(m, name))) return false;
|
|
761
|
+
if (hasMarker(type)) return true;
|
|
762
|
+
if (o.include?.some((m) => matches(m, name))) return true;
|
|
763
|
+
if (o.trackAllComponents) return true;
|
|
764
|
+
if (o.trackAllMemoized) return isMemo(type) || isPureClass(type);
|
|
765
|
+
return false;
|
|
766
|
+
}
|
|
767
|
+
function init(options = {}) {
|
|
768
|
+
const s = (0, import_state.getState)();
|
|
769
|
+
s.options = { ...options };
|
|
770
|
+
s.printed.clear();
|
|
771
|
+
if (!s.enabled) {
|
|
772
|
+
s.detach = attach();
|
|
773
|
+
s.enabled = true;
|
|
774
|
+
}
|
|
775
|
+
return disable;
|
|
776
|
+
}
|
|
777
|
+
function configure(options) {
|
|
778
|
+
const s = (0, import_state.getState)();
|
|
779
|
+
s.options = { ...s.options, ...options };
|
|
780
|
+
}
|
|
781
|
+
function disable() {
|
|
782
|
+
const s = (0, import_state.getState)();
|
|
783
|
+
if (!s.enabled) return;
|
|
784
|
+
s.detach?.();
|
|
785
|
+
s.detach = null;
|
|
786
|
+
s.enabled = false;
|
|
787
|
+
}
|
|
788
|
+
function isEnabled() {
|
|
789
|
+
return (0, import_state.getState)().enabled;
|
|
790
|
+
}
|
|
791
|
+
function track(component, name) {
|
|
792
|
+
const t = component;
|
|
793
|
+
t[import_types.MARKER] = true;
|
|
794
|
+
if (name) t.displayName = name;
|
|
795
|
+
return component;
|
|
796
|
+
}
|
|
797
|
+
|
|
367
798
|
// src/hookNames.ts
|
|
799
|
+
var hookNames_exports = {};
|
|
800
|
+
__export(hookNames_exports, {
|
|
801
|
+
HOOK_NODE_COUNT: () => NODE_COUNT,
|
|
802
|
+
clearHookNameCache: () => clearHookNameCache,
|
|
803
|
+
customHooksFromStack: () => customHooksFromStack,
|
|
804
|
+
resolveHookNames: () => resolveHookNames
|
|
805
|
+
});
|
|
806
|
+
var NODE_COUNT = {
|
|
807
|
+
useState: 1,
|
|
808
|
+
useReducer: 1,
|
|
809
|
+
useRef: 1,
|
|
810
|
+
useMemo: 1,
|
|
811
|
+
useCallback: 1,
|
|
812
|
+
useEffect: 1,
|
|
813
|
+
useLayoutEffect: 1,
|
|
814
|
+
useInsertionEffect: 1,
|
|
815
|
+
useImperativeHandle: 1,
|
|
816
|
+
useSyncExternalStore: 2,
|
|
817
|
+
useTransition: 2,
|
|
818
|
+
useDeferredValue: 1,
|
|
819
|
+
useId: 1,
|
|
820
|
+
useOptimistic: 1,
|
|
821
|
+
useActionState: 3,
|
|
822
|
+
useFormState: 3,
|
|
823
|
+
useEffectEvent: 1,
|
|
824
|
+
useCacheRefresh: 1
|
|
825
|
+
};
|
|
826
|
+
var BUILTIN_HOOKS = /* @__PURE__ */ new Set([...Object.keys(NODE_COUNT), "useContext", "useDebugValue", "use"]);
|
|
368
827
|
var noop = () => {
|
|
369
828
|
};
|
|
370
829
|
function customHooksFromStack(stack, componentName, marker) {
|
|
@@ -379,7 +838,7 @@ var RerenderLens = (function (exports) {
|
|
|
379
838
|
continue;
|
|
380
839
|
}
|
|
381
840
|
if (name === componentName || name.endsWith("." + componentName)) break;
|
|
382
|
-
if (/^use[A-Z0-9_]/.test(name)) names.push(name);
|
|
841
|
+
if (/^use[A-Z0-9_]/.test(name) && !BUILTIN_HOOKS.has(name)) names.push(name);
|
|
383
842
|
if (names.length > 8) break;
|
|
384
843
|
}
|
|
385
844
|
return names;
|
|
@@ -528,6 +987,8 @@ var RerenderLens = (function (exports) {
|
|
|
528
987
|
}
|
|
529
988
|
return result.byNode;
|
|
530
989
|
}
|
|
990
|
+
function clearHookNameCache() {
|
|
991
|
+
}
|
|
531
992
|
|
|
532
993
|
// src/fiber.ts
|
|
533
994
|
var FunctionComponent = 0;
|
|
@@ -616,10 +1077,10 @@ var RerenderLens = (function (exports) {
|
|
|
616
1077
|
try {
|
|
617
1078
|
onCommit(root, priorityLabel(priority));
|
|
618
1079
|
} catch (err) {
|
|
619
|
-
warnOnce("commit", `failed to inspect a commit: ${String(err)}`);
|
|
1080
|
+
(0, import_state2.warnOnce)("commit", `failed to inspect a commit: ${String(err)}`);
|
|
620
1081
|
} finally {
|
|
621
1082
|
const spent = nowMs() - started;
|
|
622
|
-
const s = getState();
|
|
1083
|
+
const s = (0, import_state2.getState)();
|
|
623
1084
|
s.overheadMs += spent;
|
|
624
1085
|
if (spent > s.maxCommitMs) s.maxCommitMs = spent;
|
|
625
1086
|
}
|
|
@@ -628,7 +1089,7 @@ var RerenderLens = (function (exports) {
|
|
|
628
1089
|
hook.onCommitFiberRoot = patched;
|
|
629
1090
|
const previousSchedule = hook.onScheduleFiberRoot;
|
|
630
1091
|
const patchedSchedule = function(id, root, children) {
|
|
631
|
-
getState().scheduled++;
|
|
1092
|
+
(0, import_state2.getState)().scheduled++;
|
|
632
1093
|
if (typeof previousSchedule === "function") return previousSchedule.call(this, id, root, children);
|
|
633
1094
|
};
|
|
634
1095
|
hook.onScheduleFiberRoot = patchedSchedule;
|
|
@@ -679,6 +1140,11 @@ var RerenderLens = (function (exports) {
|
|
|
679
1140
|
}
|
|
680
1141
|
return false;
|
|
681
1142
|
}
|
|
1143
|
+
function isCompiledFiber(fiber) {
|
|
1144
|
+
if (fiber.tag === ClassComponent) return false;
|
|
1145
|
+
const cache2 = fiber.updateQueue?.memoCache;
|
|
1146
|
+
return !!cache2 && Array.isArray(cache2.data);
|
|
1147
|
+
}
|
|
682
1148
|
function durationsOf(fiber) {
|
|
683
1149
|
if (typeof fiber.actualDuration !== "number") return null;
|
|
684
1150
|
const tree = fiber.actualDuration;
|
|
@@ -702,11 +1168,14 @@ var RerenderLens = (function (exports) {
|
|
|
702
1168
|
var ids = /* @__PURE__ */ new WeakMap();
|
|
703
1169
|
var fibersById = /* @__PURE__ */ new Map();
|
|
704
1170
|
var hasWeakRef = typeof WeakRef === "function";
|
|
705
|
-
|
|
1171
|
+
var pruneAt = 5e3;
|
|
1172
|
+
function remember(id, fiber) {
|
|
706
1173
|
if (!hasWeakRef) return;
|
|
1174
|
+
if (fibersById.get(id)?.deref() === fiber) return;
|
|
707
1175
|
fibersById.set(id, new WeakRef(fiber));
|
|
708
|
-
if (fibersById.size >
|
|
1176
|
+
if (fibersById.size > pruneAt) {
|
|
709
1177
|
for (const [k, ref] of fibersById) if (!ref.deref()) fibersById.delete(k);
|
|
1178
|
+
pruneAt = Math.max(5e3, fibersById.size * 2);
|
|
710
1179
|
}
|
|
711
1180
|
}
|
|
712
1181
|
function instanceIdOf(fiber) {
|
|
@@ -723,13 +1192,13 @@ var RerenderLens = (function (exports) {
|
|
|
723
1192
|
const existing = instanceIdOf(fiber);
|
|
724
1193
|
if (existing !== void 0) {
|
|
725
1194
|
ids.set(fiber, existing);
|
|
726
|
-
|
|
1195
|
+
remember(existing, fiber);
|
|
727
1196
|
return existing;
|
|
728
1197
|
}
|
|
729
|
-
const s = getState();
|
|
1198
|
+
const s = (0, import_state2.getState)();
|
|
730
1199
|
const id = s.nextInstanceId++;
|
|
731
1200
|
ids.set(fiber, id);
|
|
732
|
-
|
|
1201
|
+
remember(id, fiber);
|
|
733
1202
|
return id;
|
|
734
1203
|
}
|
|
735
1204
|
function hostNodesOf(fiber, limit = 50) {
|
|
@@ -761,7 +1230,7 @@ var RerenderLens = (function (exports) {
|
|
|
761
1230
|
}
|
|
762
1231
|
var INTERNAL_FRAME = /react-dom|react_jsx|jsx-(dev-)?runtime|\/react\/|node_modules\/react|react-stack-bottom-frame|react_stack_bottom_frame|scheduler/;
|
|
763
1232
|
function parseStackLocation(stack) {
|
|
764
|
-
for (const line of stack.split("\n")) {
|
|
1233
|
+
for (const line of stack.split("\n", 24)) {
|
|
765
1234
|
const m = /(?:at\s+(?:.*?\s+)?\(?|@)?((?:https?|file|webpack|vite|blob):[^\s()]+?):(\d+):(\d+)\)?\s*$/.exec(line.trim());
|
|
766
1235
|
if (!m || !m[1] || INTERNAL_FRAME.test(m[1])) continue;
|
|
767
1236
|
return { fileName: m[1], lineNumber: Number(m[2]), columnNumber: Number(m[3]) };
|
|
@@ -777,9 +1246,16 @@ var RerenderLens = (function (exports) {
|
|
|
777
1246
|
return out;
|
|
778
1247
|
}
|
|
779
1248
|
const st = fiber._debugStack;
|
|
780
|
-
|
|
781
|
-
|
|
1249
|
+
if (st && typeof st === "object") {
|
|
1250
|
+
if (sourceCache.has(st)) return sourceCache.get(st);
|
|
1251
|
+
const text = typeof st.stack === "string" ? st.stack : null;
|
|
1252
|
+
const out = text ? parseStackLocation(text) : void 0;
|
|
1253
|
+
sourceCache.set(st, out);
|
|
1254
|
+
return out;
|
|
1255
|
+
}
|
|
1256
|
+
return typeof st === "string" ? parseStackLocation(st) : void 0;
|
|
782
1257
|
}
|
|
1258
|
+
var sourceCache = /* @__PURE__ */ new WeakMap();
|
|
783
1259
|
function bumpCount(fiber) {
|
|
784
1260
|
const prev = counts.get(fiber) ?? (fiber.alternate ? counts.get(fiber.alternate) : void 0) ?? 0;
|
|
785
1261
|
const n = prev + 1;
|
|
@@ -803,7 +1279,7 @@ var RerenderLens = (function (exports) {
|
|
|
803
1279
|
}
|
|
804
1280
|
var isStateNode = (n) => !!n.queue && typeof n.queue.lastRenderedReducer === "function";
|
|
805
1281
|
var isStoreNode = (n) => !!n.queue && typeof n.queue.getSnapshot === "function";
|
|
806
|
-
function
|
|
1282
|
+
function hookLabel(node) {
|
|
807
1283
|
if (isStoreNode(node)) return "useSyncExternalStore";
|
|
808
1284
|
if (isStateNode(node)) {
|
|
809
1285
|
const r = node.queue.lastRenderedReducer;
|
|
@@ -828,7 +1304,7 @@ var RerenderLens = (function (exports) {
|
|
|
828
1304
|
let i = 0;
|
|
829
1305
|
for (let n = first; n; n = n.next, i++) {
|
|
830
1306
|
if (!isStateNode(n) && !isStoreNode(n)) continue;
|
|
831
|
-
const hook = labels?.[i] ??
|
|
1307
|
+
const hook = labels?.[i] ?? hookLabel(n);
|
|
832
1308
|
out.push({ path: `${hook}#${i}`, hook, index: i, value: n.memoizedState });
|
|
833
1309
|
}
|
|
834
1310
|
return out;
|
|
@@ -847,13 +1323,14 @@ var RerenderLens = (function (exports) {
|
|
|
847
1323
|
const labels = hookLabelsFor(fiber, b);
|
|
848
1324
|
let i = 0;
|
|
849
1325
|
while (a && b) {
|
|
850
|
-
|
|
851
|
-
|
|
1326
|
+
const deferred = labels?.[i] === "useDeferredValue";
|
|
1327
|
+
if ((deferred || isStateNode(b) || isStoreNode(b)) && !Object.is(a.memoizedState, b.memoizedState)) {
|
|
1328
|
+
const hook = labels?.[i] ?? hookLabel(b);
|
|
852
1329
|
out.push({
|
|
853
1330
|
path: `${hook}#${i}`,
|
|
854
1331
|
hook,
|
|
855
1332
|
index: i,
|
|
856
|
-
kind: classify(a.memoizedState, b.memoizedState),
|
|
1333
|
+
kind: (0, import_diff.classify)(a.memoizedState, b.memoizedState),
|
|
857
1334
|
prev: a.memoizedState,
|
|
858
1335
|
next: b.memoizedState
|
|
859
1336
|
});
|
|
@@ -875,12 +1352,16 @@ var RerenderLens = (function (exports) {
|
|
|
875
1352
|
}
|
|
876
1353
|
return null;
|
|
877
1354
|
}
|
|
878
|
-
var
|
|
1355
|
+
var isPlainObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v) && Object.getPrototypeOf(v) === Object.prototype;
|
|
879
1356
|
function diffContexts(fiber, alt) {
|
|
880
1357
|
const out = [];
|
|
881
1358
|
let a = alt.dependencies?.firstContext ?? null;
|
|
882
1359
|
let b = fiber.dependencies?.firstContext ?? null;
|
|
883
1360
|
let i = 0;
|
|
1361
|
+
if (b && !("memoizedValue" in b)) {
|
|
1362
|
+
(0, import_state2.warnOnce)("contextValues", "this React does not record context values on the fiber (React < 18): context changes are reported as plain parent re-renders.");
|
|
1363
|
+
return out;
|
|
1364
|
+
}
|
|
884
1365
|
while (a && b) {
|
|
885
1366
|
if (a.context === b.context && !Object.is(a.memoizedValue, b.memoizedValue)) {
|
|
886
1367
|
const name = b.context.displayName ?? "Context";
|
|
@@ -888,7 +1369,7 @@ var RerenderLens = (function (exports) {
|
|
|
888
1369
|
path: `useContext(${name})`,
|
|
889
1370
|
hook: "useContext",
|
|
890
1371
|
index: i,
|
|
891
|
-
kind: classify(a.memoizedValue, b.memoizedValue),
|
|
1372
|
+
kind: (0, import_diff.classify)(a.memoizedValue, b.memoizedValue),
|
|
892
1373
|
prev: a.memoizedValue,
|
|
893
1374
|
next: b.memoizedValue
|
|
894
1375
|
};
|
|
@@ -897,7 +1378,7 @@ var RerenderLens = (function (exports) {
|
|
|
897
1378
|
const path = componentPath(provider);
|
|
898
1379
|
change.provider = { component: path[path.length - 1] ?? null, path };
|
|
899
1380
|
}
|
|
900
|
-
if (
|
|
1381
|
+
if (isPlainObject(a.memoizedValue) && isPlainObject(b.memoizedValue)) {
|
|
901
1382
|
const prev = a.memoizedValue;
|
|
902
1383
|
const next = b.memoizedValue;
|
|
903
1384
|
const keys = /* @__PURE__ */ new Set([...Object.keys(prev), ...Object.keys(next)]);
|
|
@@ -912,16 +1393,34 @@ var RerenderLens = (function (exports) {
|
|
|
912
1393
|
}
|
|
913
1394
|
return out;
|
|
914
1395
|
}
|
|
915
|
-
var
|
|
1396
|
+
var isGenuine = (c) => c.kind === "different" || c.kind === "added" || c.kind === "removed";
|
|
1397
|
+
var isRefObject = (v) => {
|
|
1398
|
+
if (typeof v !== "object" || v === null) return false;
|
|
1399
|
+
const keys = Object.keys(v);
|
|
1400
|
+
return keys.length === 1 && keys[0] === "current";
|
|
1401
|
+
};
|
|
1402
|
+
function diffProps(prev, next) {
|
|
1403
|
+
if (prev === next) return [];
|
|
1404
|
+
const pr = prev.ref;
|
|
1405
|
+
const nr = next.ref;
|
|
1406
|
+
if (pr !== nr && isRefObject(pr) && isRefObject(nr)) {
|
|
1407
|
+
const { ref: _p, ...restPrev } = prev;
|
|
1408
|
+
const { ref: _n, ...restNext } = next;
|
|
1409
|
+
void _p;
|
|
1410
|
+
void _n;
|
|
1411
|
+
return [{ path: "ref", kind: "deep-equal", prev: pr, next: nr }, ...(0, import_diff.diffRecords)(restPrev, restNext)];
|
|
1412
|
+
}
|
|
1413
|
+
return (0, import_diff.diffRecords)(prev, next);
|
|
1414
|
+
}
|
|
916
1415
|
function analyze(fiber, alt, trackHooks) {
|
|
917
1416
|
const prevProps = alt.memoizedProps ?? {};
|
|
918
1417
|
const nextProps = fiber.memoizedProps ?? {};
|
|
919
|
-
const propChanges =
|
|
1418
|
+
const propChanges = diffProps(prevProps, nextProps);
|
|
920
1419
|
let stateChanges = [];
|
|
921
1420
|
let hookChanges = [];
|
|
922
1421
|
if (fiber.tag === ClassComponent) {
|
|
923
1422
|
if (alt.memoizedState !== fiber.memoizedState) {
|
|
924
|
-
stateChanges = diffRecords(
|
|
1423
|
+
stateChanges = (0, import_diff.diffRecords)(
|
|
925
1424
|
alt.memoizedState ?? {},
|
|
926
1425
|
fiber.memoizedState ?? {}
|
|
927
1426
|
);
|
|
@@ -929,11 +1428,11 @@ var RerenderLens = (function (exports) {
|
|
|
929
1428
|
} else if (trackHooks) {
|
|
930
1429
|
hookChanges = [...diffHooks(fiber, alt), ...diffContexts(fiber, alt)];
|
|
931
1430
|
}
|
|
932
|
-
const isStateHook = (h) => h.hook !== "useContext" && h.hook !== "useSyncExternalStore";
|
|
1431
|
+
const isStateHook = (h) => h.hook !== "useContext" && h.hook !== "useSyncExternalStore" && h.hook !== "useDeferredValue";
|
|
933
1432
|
const causes = [];
|
|
934
|
-
if (propChanges.some(
|
|
935
|
-
if (stateChanges.some(
|
|
936
|
-
if (hookChanges.some((h) => !isStateHook(h) &&
|
|
1433
|
+
if (propChanges.some(isGenuine)) causes.push("props");
|
|
1434
|
+
if (stateChanges.some(isGenuine) || hookChanges.some((h) => isStateHook(h) && isGenuine(h))) causes.push("state");
|
|
1435
|
+
if (hookChanges.some((h) => !isStateHook(h) && isGenuine(h))) causes.push("hooks");
|
|
937
1436
|
const trigger = causes.length === 0 ? "parent" : causes.length === 1 ? causes[0] : "mixed";
|
|
938
1437
|
return { propChanges, stateChanges, hookChanges, trigger };
|
|
939
1438
|
}
|
|
@@ -967,8 +1466,28 @@ var RerenderLens = (function (exports) {
|
|
|
967
1466
|
}
|
|
968
1467
|
var lastCommit = null;
|
|
969
1468
|
var EFFECT_LOOP_WINDOW_MS = 50;
|
|
1469
|
+
var MAX_REPORTS_PER_COMMIT = 200;
|
|
1470
|
+
var COMMIT_TIME_BUDGET_MS = 25;
|
|
1471
|
+
function isDeferredCatchUp(fiber) {
|
|
1472
|
+
const types = fiber._debugHookTypes;
|
|
1473
|
+
if (!types || !types.includes("useDeferredValue") || !fiber.alternate) return false;
|
|
1474
|
+
const first = fiber.memoizedState;
|
|
1475
|
+
if (!isHookList(first)) return false;
|
|
1476
|
+
const labels = hookLabelsFor(fiber, first);
|
|
1477
|
+
if (!labels) return false;
|
|
1478
|
+
let a = fiber.alternate.memoizedState;
|
|
1479
|
+
let b = first;
|
|
1480
|
+
for (let i = 0; a && b; a = a.next, b = b.next, i++) {
|
|
1481
|
+
if (labels[i] === "useDeferredValue" && !Object.is(a.memoizedState, b.memoizedState)) return true;
|
|
1482
|
+
}
|
|
1483
|
+
return false;
|
|
1484
|
+
}
|
|
1485
|
+
function isUnder(fiber, boundaries) {
|
|
1486
|
+
for (let f = fiber.return; f && f.tag !== HostRoot; f = f.return) if (f.tag === SuspenseComponent && boundaries.includes(f)) return true;
|
|
1487
|
+
return false;
|
|
1488
|
+
}
|
|
970
1489
|
function onCommit(root, commitPriority) {
|
|
971
|
-
const s = getState();
|
|
1490
|
+
const s = (0, import_state2.getState)();
|
|
972
1491
|
if (!s.enabled) return;
|
|
973
1492
|
s.commits++;
|
|
974
1493
|
const o = s.options;
|
|
@@ -976,7 +1495,7 @@ var RerenderLens = (function (exports) {
|
|
|
976
1495
|
const rendered = [];
|
|
977
1496
|
const renderedNames = /* @__PURE__ */ new Set();
|
|
978
1497
|
let hot = false;
|
|
979
|
-
let
|
|
1498
|
+
let resolvedBoundaries = null;
|
|
980
1499
|
const stack = [root.current];
|
|
981
1500
|
while (stack.length) {
|
|
982
1501
|
const fiber = stack.pop();
|
|
@@ -986,7 +1505,7 @@ var RerenderLens = (function (exports) {
|
|
|
986
1505
|
renderedNames.add(fiberName(fiber));
|
|
987
1506
|
if (shouldTrack(fiberType(fiber), o)) rendered.push(fiber);
|
|
988
1507
|
}
|
|
989
|
-
if (fiber.tag === SuspenseComponent && alt && alt.memoizedState !== null && fiber.memoizedState === null)
|
|
1508
|
+
if (fiber.tag === SuspenseComponent && alt && alt.memoizedState !== null && fiber.memoizedState === null) (resolvedBoundaries ?? (resolvedBoundaries = [])).push(fiber);
|
|
990
1509
|
if (!alt || fiber.child !== alt.child) {
|
|
991
1510
|
for (let c = fiber.child; c; c = c.sibling) stack.push(c);
|
|
992
1511
|
}
|
|
@@ -997,10 +1516,11 @@ var RerenderLens = (function (exports) {
|
|
|
997
1516
|
const updaters = updatersOf(root);
|
|
998
1517
|
let commitCause;
|
|
999
1518
|
let afterCommit;
|
|
1000
|
-
|
|
1519
|
+
const inputDriven = commitPriority === "immediate" || commitPriority === "user-blocking";
|
|
1520
|
+
if (!inputDriven && lastCommit && at - lastCommit.at < EFFECT_LOOP_WINDOW_MS && updaters.some((u) => lastCommit.rendered.has(u)) && !rendered.some(isDeferredCatchUp)) {
|
|
1001
1521
|
commitCause = "effect-after-commit";
|
|
1002
1522
|
afterCommit = lastCommit.id;
|
|
1003
|
-
} else if (
|
|
1523
|
+
} else if (resolvedBoundaries) commitCause = "suspense-resolved";
|
|
1004
1524
|
if (rendered.length === 0) {
|
|
1005
1525
|
lastCommit = { id: s.nextCommitId, at, rendered: renderedNames };
|
|
1006
1526
|
return;
|
|
@@ -1009,153 +1529,414 @@ var RerenderLens = (function (exports) {
|
|
|
1009
1529
|
lastCommit = { id: commitId, at, rendered: renderedNames };
|
|
1010
1530
|
const dispatcherRef = o.resolveHookNames ? getDispatcherRef() : null;
|
|
1011
1531
|
const parentCache = /* @__PURE__ */ new Map();
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1532
|
+
const endDiffScope = (0, import_diff.beginDiffScope)();
|
|
1533
|
+
const deadline = at + COMMIT_TIME_BUDGET_MS;
|
|
1534
|
+
try {
|
|
1535
|
+
for (let i = 0; i < rendered.length; i++) {
|
|
1536
|
+
if (i >= MAX_REPORTS_PER_COMMIT || (i & 15) === 15 && nowMs() > deadline) {
|
|
1537
|
+
s.truncated += rendered.length - i;
|
|
1538
|
+
(0, import_state2.warnOnce)("truncated", `a commit rendered ${rendered.length} tracked components; only ${i} were reported (see info().truncated). Narrow \`include\` or turn off includeState.`);
|
|
1539
|
+
break;
|
|
1540
|
+
}
|
|
1541
|
+
const fiber = rendered[i];
|
|
1542
|
+
const alt = fiber.alternate;
|
|
1543
|
+
const a = analyze(fiber, alt, trackHooks);
|
|
1544
|
+
const durations = durationsOf(fiber);
|
|
1545
|
+
let hookState = o.includeState !== false && trackHooks ? snapshotHooks(fiber) : void 0;
|
|
1546
|
+
if (dispatcherRef && fiber.tag !== ClassComponent && (a.hookChanges.length || hookState && hookState.length)) {
|
|
1547
|
+
const names = resolveHookNames(fiber, dispatcherRef);
|
|
1548
|
+
if (names.size) {
|
|
1549
|
+
for (const c of a.hookChanges) if (c.hook !== "useContext" && names.has(c.index)) c.custom = names.get(c.index);
|
|
1550
|
+
if (hookState) hookState = hookState.map((h) => names.has(h.index) ? { ...h, custom: names.get(h.index) } : h);
|
|
1551
|
+
}
|
|
1022
1552
|
}
|
|
1553
|
+
const report = (0, import_report.buildReport)({
|
|
1554
|
+
component: fiberName(fiber),
|
|
1555
|
+
instanceId: instanceId(fiber),
|
|
1556
|
+
renderCount: bumpCount(fiber),
|
|
1557
|
+
prevProps: alt.memoizedProps ?? {},
|
|
1558
|
+
nextProps: fiber.memoizedProps ?? {},
|
|
1559
|
+
propChanges: a.propChanges,
|
|
1560
|
+
stateChanges: a.stateChanges,
|
|
1561
|
+
hookChanges: a.hookChanges,
|
|
1562
|
+
...o.includeState !== false ? {
|
|
1563
|
+
hookState,
|
|
1564
|
+
contexts: trackHooks ? snapshotContexts(fiber) : void 0,
|
|
1565
|
+
state: fiber.tag === ClassComponent && fiber.memoizedState && typeof fiber.memoizedState === "object" ? fiber.memoizedState : void 0
|
|
1566
|
+
} : {},
|
|
1567
|
+
updaters,
|
|
1568
|
+
commitCause,
|
|
1569
|
+
afterCommit,
|
|
1570
|
+
key: fiber.key === null || fiber.key === void 0 ? null : String(fiber.key),
|
|
1571
|
+
parent: a.trigger === "parent" ? nearestRenderedAncestor(fiber, parentCache, trackHooks) : null,
|
|
1572
|
+
owner: ownerName(fiber),
|
|
1573
|
+
path: componentPath(fiber),
|
|
1574
|
+
memoized: isMemoizedFiber(fiber),
|
|
1575
|
+
compiled: isCompiledFiber(fiber),
|
|
1576
|
+
classComponent: fiber.tag === ClassComponent,
|
|
1577
|
+
revealed: resolvedBoundaries !== null && a.trigger === "parent" && isUnder(fiber, resolvedBoundaries),
|
|
1578
|
+
selfDuration: durations ? durations.self : void 0,
|
|
1579
|
+
treeDuration: durations ? durations.tree : void 0,
|
|
1580
|
+
commitId,
|
|
1581
|
+
commitPriority,
|
|
1582
|
+
source: sourceOf(fiber)
|
|
1583
|
+
});
|
|
1584
|
+
(0, import_state2.dispatch)(report);
|
|
1023
1585
|
}
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
instanceId: instanceId(fiber),
|
|
1027
|
-
renderCount: bumpCount(fiber),
|
|
1028
|
-
prevProps: alt.memoizedProps ?? {},
|
|
1029
|
-
nextProps: fiber.memoizedProps ?? {},
|
|
1030
|
-
propChanges: a.propChanges,
|
|
1031
|
-
stateChanges: a.stateChanges,
|
|
1032
|
-
hookChanges: a.hookChanges,
|
|
1033
|
-
...o.includeState !== false ? {
|
|
1034
|
-
hookState,
|
|
1035
|
-
contexts: trackHooks ? snapshotContexts(fiber) : void 0,
|
|
1036
|
-
state: fiber.tag === ClassComponent && fiber.memoizedState && typeof fiber.memoizedState === "object" ? fiber.memoizedState : void 0
|
|
1037
|
-
} : {},
|
|
1038
|
-
updaters,
|
|
1039
|
-
commitCause,
|
|
1040
|
-
afterCommit,
|
|
1041
|
-
key: fiber.key === null || fiber.key === void 0 ? null : String(fiber.key),
|
|
1042
|
-
parent: a.trigger === "parent" ? nearestRenderedAncestor(fiber, parentCache, trackHooks) : null,
|
|
1043
|
-
owner: ownerName(fiber),
|
|
1044
|
-
path: componentPath(fiber),
|
|
1045
|
-
memoized: isMemoizedFiber(fiber),
|
|
1046
|
-
selfDuration: durations ? durations.self : void 0,
|
|
1047
|
-
treeDuration: durations ? durations.tree : void 0,
|
|
1048
|
-
commitId,
|
|
1049
|
-
commitPriority,
|
|
1050
|
-
source: sourceOf(fiber)
|
|
1051
|
-
});
|
|
1052
|
-
dispatch(report);
|
|
1586
|
+
} finally {
|
|
1587
|
+
endDiffScope();
|
|
1053
1588
|
}
|
|
1054
1589
|
}
|
|
1055
1590
|
|
|
1056
|
-
//
|
|
1057
|
-
var
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1591
|
+
// vendor-rerender-lens.engine.js
|
|
1592
|
+
var parts = globalThis.__RERENDER_LENS_PARTS__ = globalThis.__RERENDER_LENS_PARTS__ || {};
|
|
1593
|
+
parts["fiber"] = fiber_exports;
|
|
1594
|
+
parts["tracker"] = tracker_exports;
|
|
1595
|
+
parts["hookNames"] = hookNames_exports;
|
|
1596
|
+
})();
|
|
1597
|
+
|
|
1598
|
+
;
|
|
1599
|
+
/* rerender-lens 0.5.0 — rerender-lens.js: devtools bridge + notifiers (window.RerenderLens). Built by scripts/build-vendor.mjs; do not edit. */
|
|
1600
|
+
"use strict";
|
|
1601
|
+
var RerenderLens = (() => {
|
|
1602
|
+
var __create = Object.create;
|
|
1603
|
+
var __defProp = Object.defineProperty;
|
|
1604
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
1605
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
1606
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
1607
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
1608
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
1609
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
1610
|
+
};
|
|
1611
|
+
var __export = (target, all) => {
|
|
1612
|
+
for (var name in all)
|
|
1613
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
1614
|
+
};
|
|
1615
|
+
var __copyProps = (to, from, except, desc) => {
|
|
1616
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
1617
|
+
for (let key of __getOwnPropNames(from))
|
|
1618
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
1619
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
1071
1620
|
}
|
|
1072
|
-
return
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1621
|
+
return to;
|
|
1622
|
+
};
|
|
1623
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
1624
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
1625
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
1626
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
1627
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
1628
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
1629
|
+
mod
|
|
1630
|
+
));
|
|
1631
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
1632
|
+
|
|
1633
|
+
// rerender-lens-part:types
|
|
1634
|
+
var require_types = __commonJS({
|
|
1635
|
+
"rerender-lens-part:types"(exports, module) {
|
|
1636
|
+
var p = globalThis.__RERENDER_LENS_PARTS__;
|
|
1637
|
+
if (!p || !p["types"]) throw new Error("rerender-lens: load vendor/rerender-lens.core.js and vendor/rerender-lens.engine.js before vendor/rerender-lens.js");
|
|
1638
|
+
module.exports = p["types"];
|
|
1639
|
+
}
|
|
1640
|
+
});
|
|
1641
|
+
|
|
1642
|
+
// rerender-lens-part:tracker
|
|
1643
|
+
var require_tracker = __commonJS({
|
|
1644
|
+
"rerender-lens-part:tracker"(exports, module) {
|
|
1645
|
+
var p = globalThis.__RERENDER_LENS_PARTS__;
|
|
1646
|
+
if (!p || !p["tracker"]) throw new Error("rerender-lens: load vendor/rerender-lens.core.js and vendor/rerender-lens.engine.js before vendor/rerender-lens.js");
|
|
1647
|
+
module.exports = p["tracker"];
|
|
1648
|
+
}
|
|
1649
|
+
});
|
|
1650
|
+
|
|
1651
|
+
// rerender-lens-part:fiber
|
|
1652
|
+
var require_fiber = __commonJS({
|
|
1653
|
+
"rerender-lens-part:fiber"(exports, module) {
|
|
1654
|
+
var p = globalThis.__RERENDER_LENS_PARTS__;
|
|
1655
|
+
if (!p || !p["fiber"]) throw new Error("rerender-lens: load vendor/rerender-lens.core.js and vendor/rerender-lens.engine.js before vendor/rerender-lens.js");
|
|
1656
|
+
module.exports = p["fiber"];
|
|
1657
|
+
}
|
|
1658
|
+
});
|
|
1659
|
+
|
|
1660
|
+
// rerender-lens-part:diff
|
|
1661
|
+
var require_diff = __commonJS({
|
|
1662
|
+
"rerender-lens-part:diff"(exports, module) {
|
|
1663
|
+
var p = globalThis.__RERENDER_LENS_PARTS__;
|
|
1664
|
+
if (!p || !p["diff"]) throw new Error("rerender-lens: load vendor/rerender-lens.core.js and vendor/rerender-lens.engine.js before vendor/rerender-lens.js");
|
|
1665
|
+
module.exports = p["diff"];
|
|
1666
|
+
}
|
|
1667
|
+
});
|
|
1668
|
+
|
|
1669
|
+
// rerender-lens-part:report
|
|
1670
|
+
var require_report = __commonJS({
|
|
1671
|
+
"rerender-lens-part:report"(exports, module) {
|
|
1672
|
+
var p = globalThis.__RERENDER_LENS_PARTS__;
|
|
1673
|
+
if (!p || !p["report"]) throw new Error("rerender-lens: load vendor/rerender-lens.core.js and vendor/rerender-lens.engine.js before vendor/rerender-lens.js");
|
|
1674
|
+
module.exports = p["report"];
|
|
1675
|
+
}
|
|
1676
|
+
});
|
|
1677
|
+
|
|
1678
|
+
// rerender-lens-part:state
|
|
1679
|
+
var require_state = __commonJS({
|
|
1680
|
+
"rerender-lens-part:state"(exports, module) {
|
|
1681
|
+
var p = globalThis.__RERENDER_LENS_PARTS__;
|
|
1682
|
+
if (!p || !p["state"]) throw new Error("rerender-lens: load vendor/rerender-lens.core.js and vendor/rerender-lens.engine.js before vendor/rerender-lens.js");
|
|
1683
|
+
module.exports = p["state"];
|
|
1684
|
+
}
|
|
1685
|
+
});
|
|
1686
|
+
|
|
1687
|
+
// rerender-lens-part:overlay
|
|
1688
|
+
var require_overlay = __commonJS({
|
|
1689
|
+
"rerender-lens-part:overlay"(exports, module) {
|
|
1690
|
+
var p = globalThis.__RERENDER_LENS_PARTS__;
|
|
1691
|
+
if (!p || !p["overlay"]) throw new Error("rerender-lens: load vendor/rerender-lens.core.js and vendor/rerender-lens.engine.js before vendor/rerender-lens.js");
|
|
1692
|
+
module.exports = p["overlay"];
|
|
1693
|
+
}
|
|
1694
|
+
});
|
|
1695
|
+
|
|
1696
|
+
// rerender-lens-part:version
|
|
1697
|
+
var require_version = __commonJS({
|
|
1698
|
+
"rerender-lens-part:version"(exports, module) {
|
|
1699
|
+
var p = globalThis.__RERENDER_LENS_PARTS__;
|
|
1700
|
+
if (!p || !p["version"]) throw new Error("rerender-lens: load vendor/rerender-lens.core.js and vendor/rerender-lens.engine.js before vendor/rerender-lens.js");
|
|
1701
|
+
module.exports = p["version"];
|
|
1702
|
+
}
|
|
1703
|
+
});
|
|
1704
|
+
|
|
1705
|
+
// src/inject.ts
|
|
1706
|
+
var inject_exports = {};
|
|
1707
|
+
__export(inject_exports, {
|
|
1708
|
+
DEVTOOLS_MARKER: () => DEVTOOLS_MARKER,
|
|
1709
|
+
MARKER: () => import_types.MARKER,
|
|
1710
|
+
PROTOCOL_VERSION: () => PROTOCOL_VERSION,
|
|
1711
|
+
VERSION: () => import_version2.VERSION,
|
|
1712
|
+
buildReport: () => import_report.buildReport,
|
|
1713
|
+
classify: () => import_diff4.classify,
|
|
1714
|
+
combineNotifiers: () => combineNotifiers,
|
|
1715
|
+
configure: () => import_tracker2.configure,
|
|
1716
|
+
createCollector: () => createCollector,
|
|
1717
|
+
createDevtoolsNotifier: () => createDevtoolsNotifier,
|
|
1718
|
+
deepEqual: () => import_diff4.deepEqual,
|
|
1719
|
+
diffRecords: () => import_diff4.diffRecords,
|
|
1720
|
+
disable: () => import_tracker2.disable,
|
|
1721
|
+
ensureDevtoolsHook: () => import_fiber2.ensureDevtoolsHook,
|
|
1722
|
+
getDisplayName: () => import_tracker2.getDisplayName,
|
|
1723
|
+
getRenderers: () => import_fiber2.getRenderers,
|
|
1724
|
+
init: () => import_tracker2.init,
|
|
1725
|
+
isEnabled: () => import_tracker2.isEnabled,
|
|
1726
|
+
isProductionReact: () => import_fiber2.isProductionReact,
|
|
1727
|
+
printReport: () => import_report.printReport,
|
|
1728
|
+
serialize: () => serialize,
|
|
1729
|
+
shouldTrack: () => import_tracker2.shouldTrack,
|
|
1730
|
+
summarize: () => import_report.summarize,
|
|
1731
|
+
track: () => import_tracker2.track
|
|
1732
|
+
});
|
|
1733
|
+
var import_types = __toESM(require_types(), 1);
|
|
1734
|
+
var import_tracker2 = __toESM(require_tracker(), 1);
|
|
1735
|
+
var import_fiber2 = __toESM(require_fiber(), 1);
|
|
1736
|
+
var import_diff4 = __toESM(require_diff(), 1);
|
|
1737
|
+
var import_report = __toESM(require_report(), 1);
|
|
1738
|
+
|
|
1739
|
+
// src/fixes.ts
|
|
1740
|
+
var import_diff2 = __toESM(require_diff(), 1);
|
|
1741
|
+
|
|
1742
|
+
// src/causes.ts
|
|
1743
|
+
var import_diff = __toESM(require_diff(), 1);
|
|
1744
|
+
var isAncestorReport = (anc, r) => anc.path.length < r.path.length && r.path[anc.path.length] === anc.component && anc.path.every((p, i) => r.path[i] === p);
|
|
1745
|
+
var bump = (m, key, n = 1) => void m.set(key, (m.get(key) || 0) + n);
|
|
1746
|
+
function indexByComponent(reports) {
|
|
1747
|
+
const index = /* @__PURE__ */ new Map();
|
|
1748
|
+
for (const r of reports) {
|
|
1749
|
+
const list = index.get(r.component);
|
|
1750
|
+
if (list) list.push(r);
|
|
1751
|
+
else index.set(r.component, [r]);
|
|
1752
|
+
}
|
|
1753
|
+
return index;
|
|
1754
|
+
}
|
|
1755
|
+
function rootCauseOf(r, commitReports, index = indexByComponent(commitReports)) {
|
|
1756
|
+
let cur = r;
|
|
1757
|
+
const seen = /* @__PURE__ */ new Set([r]);
|
|
1758
|
+
while (cur.trigger === "parent" && cur.parent) {
|
|
1759
|
+
const parent = cur.parent;
|
|
1760
|
+
const candidates = index.get(parent.name);
|
|
1761
|
+
const p = candidates && candidates.find((x) => isAncestorReport(x, cur));
|
|
1762
|
+
if (!p || seen.has(p)) return { name: parent.name, trigger: parent.trigger, report: null };
|
|
1763
|
+
seen.add(p);
|
|
1764
|
+
cur = p;
|
|
1765
|
+
}
|
|
1766
|
+
return cur === r ? null : { name: cur.component, trigger: cur.trigger, report: cur };
|
|
1767
|
+
}
|
|
1768
|
+
function rootCausesOf(reports) {
|
|
1769
|
+
const roots = /* @__PURE__ */ new Map();
|
|
1770
|
+
const rootByReport = /* @__PURE__ */ new Map();
|
|
1771
|
+
const index = indexByComponent(reports);
|
|
1772
|
+
let avoidable = 0;
|
|
1773
|
+
let wasted = 0;
|
|
1774
|
+
for (const r of reports) {
|
|
1775
|
+
if (!r.avoidable) continue;
|
|
1776
|
+
avoidable++;
|
|
1777
|
+
if (typeof r.selfDuration === "number") wasted += r.selfDuration;
|
|
1778
|
+
const root = rootCauseOf(r, reports, index);
|
|
1779
|
+
const name = root ? root.name : r.parent && r.parent.name || "(unknown)";
|
|
1780
|
+
const trigger = root ? root.trigger : r.parent && r.parent.trigger || "parent";
|
|
1781
|
+
rootByReport.set(r, name);
|
|
1782
|
+
let agg = roots.get(name);
|
|
1783
|
+
if (!agg) {
|
|
1784
|
+
agg = { name, trigger, count: 0, components: /* @__PURE__ */ new Map() };
|
|
1785
|
+
roots.set(name, agg);
|
|
1786
|
+
}
|
|
1787
|
+
agg.count++;
|
|
1788
|
+
bump(agg.components, r.component);
|
|
1103
1789
|
}
|
|
1104
|
-
return
|
|
1105
|
-
}
|
|
1106
|
-
function configure(options) {
|
|
1107
|
-
const s = getState();
|
|
1108
|
-
s.options = { ...s.options, ...options };
|
|
1790
|
+
return { roots: [...roots.values()].sort((a, b) => b.count - a.count), rootByReport, avoidable, wasted };
|
|
1109
1791
|
}
|
|
1110
|
-
function
|
|
1111
|
-
const
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1792
|
+
function groupByCommit(reports) {
|
|
1793
|
+
const out = /* @__PURE__ */ new Map();
|
|
1794
|
+
for (const r of reports) {
|
|
1795
|
+
if (typeof r.commitId !== "number" || r.commitId <= 0) continue;
|
|
1796
|
+
const list = out.get(r.commitId);
|
|
1797
|
+
if (list) list.push(r);
|
|
1798
|
+
else out.set(r.commitId, [r]);
|
|
1799
|
+
}
|
|
1800
|
+
return out;
|
|
1116
1801
|
}
|
|
1117
|
-
function
|
|
1118
|
-
|
|
1802
|
+
function rankRootCauses(reports) {
|
|
1803
|
+
const byName = /* @__PURE__ */ new Map();
|
|
1804
|
+
for (const commit of groupByCommit(reports).values()) {
|
|
1805
|
+
for (const root of rootCausesOf(commit).roots) {
|
|
1806
|
+
let agg = byName.get(root.name);
|
|
1807
|
+
if (!agg) {
|
|
1808
|
+
agg = { name: root.name, trigger: root.trigger, commits: 0, count: 0, components: /* @__PURE__ */ new Map() };
|
|
1809
|
+
byName.set(root.name, agg);
|
|
1810
|
+
}
|
|
1811
|
+
agg.commits++;
|
|
1812
|
+
agg.count += root.count;
|
|
1813
|
+
for (const [c, n] of root.components) bump(agg.components, c, n);
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
return [...byName.values()].sort((a, b) => b.count - a.count || b.commits - a.commits || a.name.localeCompare(b.name));
|
|
1119
1817
|
}
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1818
|
+
var plural = (n, word) => `${n} ${word}${n === 1 ? "" : "s"}`;
|
|
1819
|
+
function formatRootCauses(reports, limit = 5) {
|
|
1820
|
+
const ranked = rankRootCauses(reports);
|
|
1821
|
+
const lines = ranked.slice(0, limit).map((root, i) => `${String(i + 1).padStart(2)}. <${root.name}> (${root.trigger}) started ${plural(root.commits, "commit")}, ${plural(root.count, "avoidable re-render")} (${[...root.components].map(([c, n]) => `<${c}>${n > 1 ? " x" + n : ""}`).join(", ")})`);
|
|
1822
|
+
if (ranked.length > limit) lines.push(` \u2026 ${ranked.length - limit} more`);
|
|
1823
|
+
return lines.join("\n");
|
|
1125
1824
|
}
|
|
1126
1825
|
|
|
1127
1826
|
// src/fixes.ts
|
|
1128
|
-
var
|
|
1827
|
+
var MAX_FIX_REPORTS = 50;
|
|
1129
1828
|
var rootOf = (path) => path.split(/[.[]/)[0] || path;
|
|
1829
|
+
var identifier = (name) => /^[A-Za-z_$][\w$]*$/.test(name) ? name : "value";
|
|
1830
|
+
function shortValue(v, max = 60) {
|
|
1831
|
+
let s;
|
|
1832
|
+
try {
|
|
1833
|
+
s = JSON.stringify(v);
|
|
1834
|
+
} catch {
|
|
1835
|
+
s = String(v);
|
|
1836
|
+
}
|
|
1837
|
+
if (s === void 0) s = String(v);
|
|
1838
|
+
return s.length > max ? s.slice(0, max - 3) + "..." : s;
|
|
1839
|
+
}
|
|
1130
1840
|
function fixesFor(r) {
|
|
1131
1841
|
const out = [];
|
|
1132
|
-
const
|
|
1133
|
-
const
|
|
1842
|
+
const ownerName = r.owner || r.parent && r.parent.name || null;
|
|
1843
|
+
const propChanges = r.propChanges || [];
|
|
1844
|
+
const changes = [...propChanges, ...r.stateChanges || [], ...r.hookChanges || []];
|
|
1134
1845
|
if (r.avoidable && (changes.length === 0 || r.memoized === false)) {
|
|
1846
|
+
const identical = changes.length === 0;
|
|
1135
1847
|
out.push({
|
|
1136
1848
|
kind: "memo",
|
|
1137
1849
|
owner: r.component,
|
|
1138
1850
|
target: r.component,
|
|
1139
1851
|
prop: null,
|
|
1140
1852
|
label: `Wrap <${r.component}> in React.memo`,
|
|
1141
|
-
detail:
|
|
1853
|
+
detail: identical ? `<${r.component}> re-rendered with identical props because <${r.parent && r.parent.name || "its parent"}> re-rendered.` : `<${r.component}> is not memoized: fixing its props alone will not stop the re-render.`,
|
|
1854
|
+
snippet: `// ${r.component}
|
|
1855
|
+
import { memo } from 'react';
|
|
1856
|
+
|
|
1857
|
+
export const ${r.component} = memo(function ${r.component}(props) {
|
|
1858
|
+
// ...
|
|
1859
|
+
});
|
|
1860
|
+
// class components: extend PureComponent instead`
|
|
1142
1861
|
});
|
|
1143
1862
|
}
|
|
1144
|
-
for (const c of
|
|
1145
|
-
if (!
|
|
1863
|
+
for (const c of propChanges) {
|
|
1864
|
+
if (!import_diff2.AVOIDABLE_KINDS.has(c.kind)) continue;
|
|
1865
|
+
const owner = ownerName || "?";
|
|
1146
1866
|
const root = rootOf(c.path);
|
|
1867
|
+
const id = identifier(root);
|
|
1147
1868
|
if (root === "children" && (c.kind === "element" || c.kind === "deep-equal")) {
|
|
1148
|
-
out.push({
|
|
1869
|
+
out.push({
|
|
1870
|
+
kind: "children",
|
|
1871
|
+
owner,
|
|
1872
|
+
target: r.component,
|
|
1873
|
+
prop: "children",
|
|
1874
|
+
label: `memoize children of <${r.component}> in <${owner}>`,
|
|
1875
|
+
detail: `<${owner}> re-creates the children of <${r.component}> on every render; they have the same types and props each time.`,
|
|
1876
|
+
snippet: `// ${owner}
|
|
1877
|
+
import { useMemo } from 'react';
|
|
1878
|
+
|
|
1879
|
+
const children = useMemo(() => (
|
|
1880
|
+
<>{/* the same elements */}</>
|
|
1881
|
+
), [/* deps */]);
|
|
1882
|
+
|
|
1883
|
+
<${r.component}>{children}</${r.component}>
|
|
1884
|
+
|
|
1885
|
+
// static children: hoist them to module scope
|
|
1886
|
+
const STATIC = <em>hi</em>;`
|
|
1887
|
+
});
|
|
1149
1888
|
} else if (c.kind === "function") {
|
|
1150
|
-
out.push({
|
|
1889
|
+
out.push({
|
|
1890
|
+
kind: "useCallback",
|
|
1891
|
+
owner,
|
|
1892
|
+
target: r.component,
|
|
1893
|
+
prop: root,
|
|
1894
|
+
label: `useCallback(${root}) in <${owner}>`,
|
|
1895
|
+
detail: `prop "${c.path}" of <${r.component}> is a new function on every render of <${owner}>.`,
|
|
1896
|
+
snippet: `// ${owner}
|
|
1897
|
+
import { useCallback } from 'react';
|
|
1898
|
+
|
|
1899
|
+
const ${id} = useCallback((/* args */) => {
|
|
1900
|
+
// ...
|
|
1901
|
+
}, [/* deps */]);
|
|
1902
|
+
|
|
1903
|
+
<${r.component} ${root}={${id}} />`
|
|
1904
|
+
});
|
|
1151
1905
|
} else if (c.kind === "element") {
|
|
1152
|
-
out.push({
|
|
1906
|
+
out.push({
|
|
1907
|
+
kind: "useMemoElement",
|
|
1908
|
+
owner,
|
|
1909
|
+
target: r.component,
|
|
1910
|
+
prop: root,
|
|
1911
|
+
label: `memoize element prop ${root} in <${owner}>`,
|
|
1912
|
+
detail: `prop "${c.path}" of <${r.component}> is a new element with the same type and props on every render of <${owner}>.`,
|
|
1913
|
+
snippet: `// ${owner}
|
|
1914
|
+
import { useMemo } from 'react';
|
|
1915
|
+
|
|
1916
|
+
const ${id} = useMemo(() => ${shortValue(c.next, 40)}, [/* deps */]);
|
|
1917
|
+
// or pass it as children from a component that does not re-render`
|
|
1918
|
+
});
|
|
1153
1919
|
} else {
|
|
1154
|
-
|
|
1920
|
+
const isArray = Array.isArray(c.next);
|
|
1921
|
+
out.push({
|
|
1922
|
+
kind: "useMemo",
|
|
1923
|
+
owner,
|
|
1924
|
+
target: r.component,
|
|
1925
|
+
prop: root,
|
|
1926
|
+
label: `useMemo(${root}) in <${owner}>`,
|
|
1927
|
+
detail: `prop "${c.path}" of <${r.component}> is a new ${isArray ? "array" : "object"} with the same contents on every render of <${owner}>.`,
|
|
1928
|
+
snippet: `// ${owner}
|
|
1929
|
+
import { useMemo } from 'react';
|
|
1930
|
+
|
|
1931
|
+
const ${id} = useMemo(() => (${shortValue(c.next, 80)}), [/* deps */]);
|
|
1932
|
+
|
|
1933
|
+
// or, when it never changes, hoist it to module scope:
|
|
1934
|
+
const ${id.toUpperCase()} = ${shortValue(c.next, 80)};`
|
|
1935
|
+
});
|
|
1155
1936
|
}
|
|
1156
1937
|
}
|
|
1157
|
-
for (const c of [...r.stateChanges, ...r.hookChanges]) {
|
|
1158
|
-
const isContext = c.hook === "useContext";
|
|
1938
|
+
for (const c of [...r.stateChanges || [], ...r.hookChanges || []]) {
|
|
1939
|
+
const isContext = c.hook === "useContext" || /^useContext/.test(c.path);
|
|
1159
1940
|
const ctxName = isContext ? (/useContext\((.*)\)/.exec(c.path) || [])[1] || "Context" : "";
|
|
1160
1941
|
const providerOwner = isContext && c.provider && c.provider.component ? c.provider.component : null;
|
|
1161
1942
|
if (isContext && c.kind === "different" && c.changedKeys && typeof c.totalKeys === "number" && c.changedKeys.length > 0 && c.changedKeys.length < c.totalKeys) {
|
|
@@ -1165,20 +1946,63 @@ var RerenderLens = (function (exports) {
|
|
|
1165
1946
|
target: r.component,
|
|
1166
1947
|
prop: ctxName,
|
|
1167
1948
|
label: `split ${ctxName}${providerOwner ? ` in <${providerOwner}>` : ""}: only ${c.changedKeys.join(", ")} changed`,
|
|
1168
|
-
detail: `${c.changedKeys.
|
|
1949
|
+
detail: `${c.changedKeys.map((k) => `"${k}"`).join(", ")} of ${c.totalKeys} keys changed in ${ctxName}, yet every consumer (like <${r.component}>) re-rendered. Consumers that read the other keys re-render for nothing.`,
|
|
1950
|
+
snippet: `// ${providerOwner || "Provider"}
|
|
1951
|
+
// one context per independently-changing slice
|
|
1952
|
+
const ${identifier(ctxName)}Static = createContext(...);
|
|
1953
|
+
const ${identifier(ctxName)}${c.changedKeys.map((k) => k[0].toUpperCase() + k.slice(1)).join("")} = createContext(...);
|
|
1954
|
+
|
|
1955
|
+
// or keep one context and let consumers select a slice:
|
|
1956
|
+
const ${c.changedKeys[0]} = useContextSelector(${ctxName}, (v) => v.${c.changedKeys[0]});`
|
|
1169
1957
|
});
|
|
1170
1958
|
continue;
|
|
1171
1959
|
}
|
|
1172
|
-
if (!
|
|
1960
|
+
if (!import_diff2.AVOIDABLE_KINDS.has(c.kind)) continue;
|
|
1173
1961
|
if (isContext) {
|
|
1174
|
-
out.push({
|
|
1962
|
+
out.push({
|
|
1963
|
+
kind: "contextValue",
|
|
1964
|
+
owner: providerOwner || `${ctxName}.Provider`,
|
|
1965
|
+
target: r.component,
|
|
1966
|
+
prop: ctxName,
|
|
1967
|
+
label: `memoize the ${ctxName} provider value${providerOwner ? ` in <${providerOwner}>` : ""}`,
|
|
1968
|
+
detail: `<${r.component}> re-rendered because ${ctxName} produced a new value that is deep-equal to the previous one${providerOwner ? ` (Provider rendered by <${providerOwner}>)` : ""}.`,
|
|
1969
|
+
snippet: `// ${providerOwner || `where <${ctxName}.Provider> is rendered`}
|
|
1970
|
+
const value = useMemo(() => ({ /* ... */ }), [/* deps */]);
|
|
1971
|
+
<${ctxName}.Provider value={value}>`
|
|
1972
|
+
});
|
|
1175
1973
|
} else if (c.hook === "useSyncExternalStore") {
|
|
1176
1974
|
const chain = c.custom || [];
|
|
1177
1975
|
const redux = chain.some((n) => /^use(App)?Selector$/.test(n));
|
|
1178
1976
|
const zustand = !redux && chain.some((n) => /^use[A-Z]\w*Store$/.test(n) || n === "useStore" || n === "useBoundStore");
|
|
1179
|
-
|
|
1977
|
+
const via = chain.length ? ` via ${chain.join(" \u203A ")}` : "";
|
|
1978
|
+
out.push({
|
|
1979
|
+
kind: "storeSnapshot",
|
|
1980
|
+
owner: r.component,
|
|
1981
|
+
target: r.component,
|
|
1982
|
+
prop: c.path,
|
|
1983
|
+
label: redux ? `memoize the selector in <${r.component}>` : zustand ? `useShallow in <${r.component}>` : `stable getSnapshot in <${r.component}>`,
|
|
1984
|
+
detail: redux ? `the selector${via} returns a new object on every call, so the component re-renders on every store change.` : zustand ? `the store selector${via} returns a new object on every call, so the component re-renders on every store change.` : `${c.path}${via} returned a new reference with the same contents; getSnapshot must return a cached value.`,
|
|
1985
|
+
snippet: redux ? `// ${r.component}
|
|
1986
|
+
import { shallowEqual } from 'react-redux';
|
|
1987
|
+
const slice = useSelector(selectSlice, shallowEqual);
|
|
1988
|
+
// or memoize: const selectSlice = createSelector([selectA, selectB], (a, b) => ({ a, b }));` : zustand ? `// ${r.component}
|
|
1989
|
+
import { useShallow } from 'zustand/react/shallow';
|
|
1990
|
+
const { a, b } = useStore(useShallow((s) => ({ a: s.a, b: s.b })));
|
|
1991
|
+
// or select a primitive: const a = useStore((s) => s.a);` : `// ${r.component}
|
|
1992
|
+
// getSnapshot must return the same reference while the data is unchanged
|
|
1993
|
+
const snapshot = useSyncExternalStore(subscribe, store.getSnapshot /* cached */);`
|
|
1994
|
+
});
|
|
1180
1995
|
} else {
|
|
1181
|
-
out.push({
|
|
1996
|
+
out.push({
|
|
1997
|
+
kind: "bailout",
|
|
1998
|
+
owner: r.component,
|
|
1999
|
+
target: r.component,
|
|
2000
|
+
prop: c.path,
|
|
2001
|
+
label: `bail out before setting ${c.path} in <${r.component}>`,
|
|
2002
|
+
detail: `${c.path} was set to a value deep-equal to the current one (new reference).`,
|
|
2003
|
+
snippet: `// ${r.component}
|
|
2004
|
+
setState((prev) => (deepEqual(prev, next) ? prev : next));`
|
|
2005
|
+
});
|
|
1182
2006
|
}
|
|
1183
2007
|
}
|
|
1184
2008
|
return out;
|
|
@@ -1192,11 +2016,12 @@ var RerenderLens = (function (exports) {
|
|
|
1192
2016
|
const key = fixKey(f);
|
|
1193
2017
|
let agg = byKey.get(key);
|
|
1194
2018
|
if (!agg) {
|
|
1195
|
-
agg = { ...f, key, count: 0, components: {} };
|
|
2019
|
+
agg = { ...f, key, count: 0, components: {}, reports: [] };
|
|
1196
2020
|
byKey.set(key, agg);
|
|
1197
2021
|
}
|
|
1198
2022
|
agg.count++;
|
|
1199
2023
|
agg.components[r.component] = (agg.components[r.component] || 0) + 1;
|
|
2024
|
+
if (agg.reports.length < MAX_FIX_REPORTS) agg.reports.push(r);
|
|
1200
2025
|
}
|
|
1201
2026
|
}
|
|
1202
2027
|
return [...byKey.values()].sort((a, b) => b.count - a.count || a.label.localeCompare(b.label));
|
|
@@ -1206,6 +2031,8 @@ var RerenderLens = (function (exports) {
|
|
|
1206
2031
|
if (!ranked.length) return "No avoidable re-renders.";
|
|
1207
2032
|
const lines = ranked.slice(0, limit).map((f, i) => `${String(i + 1).padStart(2)}. ${f.label} (removes ${f.count}: ${Object.entries(f.components).map(([c, n]) => `<${c}>${n > 1 ? " x" + n : ""}`).join(", ")})`);
|
|
1208
2033
|
if (ranked.length > limit) lines.push(` \u2026 ${ranked.length - limit} more`);
|
|
2034
|
+
const roots = formatRootCauses(reports, 5);
|
|
2035
|
+
if (roots) lines.push("", "Root causes:", roots);
|
|
1209
2036
|
return lines.join("\n");
|
|
1210
2037
|
}
|
|
1211
2038
|
|
|
@@ -1242,25 +2069,25 @@ var RerenderLens = (function (exports) {
|
|
|
1242
2069
|
|
|
1243
2070
|
// src/budget.ts
|
|
1244
2071
|
function avoidableCounts(reports) {
|
|
1245
|
-
const
|
|
1246
|
-
for (const r of reports) if (r.avoidable)
|
|
1247
|
-
return
|
|
2072
|
+
const counts = {};
|
|
2073
|
+
for (const r of reports) if (r.avoidable) counts[r.component] = (counts[r.component] || 0) + 1;
|
|
2074
|
+
return counts;
|
|
1248
2075
|
}
|
|
1249
2076
|
function checkBudget(reports, budget) {
|
|
1250
2077
|
const b = typeof budget === "number" ? { "*": budget } : budget;
|
|
1251
2078
|
const fallback = typeof b["*"] === "number" ? b["*"] : 0;
|
|
1252
|
-
const
|
|
2079
|
+
const counts = avoidableCounts(reports);
|
|
1253
2080
|
const violations = [];
|
|
1254
2081
|
const slack = [];
|
|
1255
|
-
const names = /* @__PURE__ */ new Set([...Object.keys(
|
|
2082
|
+
const names = /* @__PURE__ */ new Set([...Object.keys(counts), ...Object.keys(b).filter((k) => k !== "*")]);
|
|
1256
2083
|
for (const component of names) {
|
|
1257
2084
|
const allowed = typeof b[component] === "number" ? b[component] : fallback;
|
|
1258
|
-
const avoidable =
|
|
2085
|
+
const avoidable = counts[component] || 0;
|
|
1259
2086
|
if (avoidable > allowed) violations.push({ component, avoidable, allowed });
|
|
1260
2087
|
else if (avoidable < allowed) slack.push({ component, avoidable, allowed });
|
|
1261
2088
|
}
|
|
1262
2089
|
violations.sort((x, y) => y.avoidable - y.allowed - (x.avoidable - x.allowed));
|
|
1263
|
-
return { ok: violations.length === 0, violations, slack, counts
|
|
2090
|
+
return { ok: violations.length === 0, violations, slack, counts };
|
|
1264
2091
|
}
|
|
1265
2092
|
function assertWithinBudget(reports, budget) {
|
|
1266
2093
|
const result = checkBudget(reports, budget);
|
|
@@ -1310,101 +2137,19 @@ ${formatFixes(reports)}`);
|
|
|
1310
2137
|
};
|
|
1311
2138
|
}
|
|
1312
2139
|
|
|
1313
|
-
// src/overlay.ts
|
|
1314
|
-
var ROOT_ID = "rerender-lens-overlay";
|
|
1315
|
-
var layer = null;
|
|
1316
|
-
function ensureLayer() {
|
|
1317
|
-
if (typeof document === "undefined" || !document.body) return null;
|
|
1318
|
-
if (layer && layer.root.isConnected) return layer;
|
|
1319
|
-
let root = document.getElementById(ROOT_ID);
|
|
1320
|
-
if (!root) {
|
|
1321
|
-
root = document.createElement("div");
|
|
1322
|
-
root.id = ROOT_ID;
|
|
1323
|
-
root.setAttribute("aria-hidden", "true");
|
|
1324
|
-
Object.assign(root.style, {
|
|
1325
|
-
position: "fixed",
|
|
1326
|
-
inset: "0",
|
|
1327
|
-
pointerEvents: "none",
|
|
1328
|
-
zIndex: "2147483647",
|
|
1329
|
-
overflow: "visible"
|
|
1330
|
-
});
|
|
1331
|
-
document.body.appendChild(root);
|
|
1332
|
-
}
|
|
1333
|
-
layer = { root, sticky: [] };
|
|
1334
|
-
return layer;
|
|
1335
|
-
}
|
|
1336
|
-
function box(rect, color, fill, label) {
|
|
1337
|
-
const b = document.createElement("div");
|
|
1338
|
-
Object.assign(b.style, {
|
|
1339
|
-
position: "absolute",
|
|
1340
|
-
left: `${rect.left}px`,
|
|
1341
|
-
top: `${rect.top}px`,
|
|
1342
|
-
width: `${Math.max(rect.width, 2)}px`,
|
|
1343
|
-
height: `${Math.max(rect.height, 2)}px`,
|
|
1344
|
-
boxSizing: "border-box",
|
|
1345
|
-
border: `2px solid ${color}`,
|
|
1346
|
-
background: fill,
|
|
1347
|
-
borderRadius: "2px"
|
|
1348
|
-
});
|
|
1349
|
-
if (label) {
|
|
1350
|
-
const tag = document.createElement("span");
|
|
1351
|
-
tag.textContent = label;
|
|
1352
|
-
Object.assign(tag.style, {
|
|
1353
|
-
position: "absolute",
|
|
1354
|
-
left: "-2px",
|
|
1355
|
-
top: rect.top > 20 ? "-20px" : "100%",
|
|
1356
|
-
font: "11px/16px system-ui, sans-serif",
|
|
1357
|
-
color: "#fff",
|
|
1358
|
-
background: color,
|
|
1359
|
-
padding: "1px 5px",
|
|
1360
|
-
borderRadius: "2px",
|
|
1361
|
-
whiteSpace: "nowrap"
|
|
1362
|
-
});
|
|
1363
|
-
b.appendChild(tag);
|
|
1364
|
-
}
|
|
1365
|
-
return b;
|
|
1366
|
-
}
|
|
1367
|
-
function highlight(target) {
|
|
1368
|
-
const l = ensureLayer();
|
|
1369
|
-
if (!l) return;
|
|
1370
|
-
for (const s of l.sticky) s.remove();
|
|
1371
|
-
l.sticky = [];
|
|
1372
|
-
if (!target) return;
|
|
1373
|
-
for (const node of target.nodes) {
|
|
1374
|
-
const rect = node.getBoundingClientRect();
|
|
1375
|
-
if (rect.width === 0 && rect.height === 0) continue;
|
|
1376
|
-
const b = box(rect, "#1a73e8", "rgba(26, 115, 232, 0.12)", target.label);
|
|
1377
|
-
l.root.appendChild(b);
|
|
1378
|
-
l.sticky.push(b);
|
|
1379
|
-
}
|
|
1380
|
-
}
|
|
1381
|
-
function clearHighlight() {
|
|
1382
|
-
highlight(null);
|
|
1383
|
-
}
|
|
1384
|
-
function flash(target, duration = 500) {
|
|
1385
|
-
const l = ensureLayer();
|
|
1386
|
-
if (!l) return;
|
|
1387
|
-
for (const node of target.nodes) {
|
|
1388
|
-
const rect = node.getBoundingClientRect();
|
|
1389
|
-
if (rect.width === 0 && rect.height === 0) continue;
|
|
1390
|
-
const b = box(rect, "#d93025", "rgba(217, 48, 37, 0.15)");
|
|
1391
|
-
b.style.transition = `opacity ${duration}ms ease-out`;
|
|
1392
|
-
l.root.appendChild(b);
|
|
1393
|
-
requestAnimationFrame(() => {
|
|
1394
|
-
b.style.opacity = "0";
|
|
1395
|
-
});
|
|
1396
|
-
setTimeout(() => b.remove(), duration + 50);
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
|
|
1400
|
-
// src/version.ts
|
|
1401
|
-
var VERSION = "0.3.0" ;
|
|
1402
|
-
|
|
1403
2140
|
// src/devtools.ts
|
|
2141
|
+
var import_diff3 = __toESM(require_diff(), 1);
|
|
2142
|
+
var import_tracker = __toESM(require_tracker(), 1);
|
|
2143
|
+
var import_state = __toESM(require_state(), 1);
|
|
2144
|
+
var import_fiber = __toESM(require_fiber(), 1);
|
|
2145
|
+
var import_overlay = __toESM(require_overlay(), 1);
|
|
2146
|
+
var import_version = __toESM(require_version(), 1);
|
|
1404
2147
|
var DEVTOOLS_MARKER = "__rerenderLens";
|
|
1405
2148
|
var PROTOCOL_VERSION = 2;
|
|
1406
2149
|
var DEFAULT_CHANNEL = "rerender-lens";
|
|
1407
|
-
|
|
2150
|
+
var SERIALIZE_MAX_ENTRIES = 100;
|
|
2151
|
+
var SERIALIZE_MAX_NODES = 2e4;
|
|
2152
|
+
function serialize(value, maxDepth = 4, seen = /* @__PURE__ */ new WeakSet(), depth = 0, budget = { nodes: SERIALIZE_MAX_NODES }) {
|
|
1408
2153
|
if (value === null || value === void 0) return value;
|
|
1409
2154
|
const t = typeof value;
|
|
1410
2155
|
if (t === "string" || t === "boolean") return value;
|
|
@@ -1415,24 +2160,56 @@ ${formatFixes(reports)}`);
|
|
|
1415
2160
|
const obj = value;
|
|
1416
2161
|
if (seen.has(obj)) return "[Circular]";
|
|
1417
2162
|
if (depth >= maxDepth) return "[\u2026]";
|
|
2163
|
+
if (--budget.nodes < 0) return "[\u2026]";
|
|
2164
|
+
const next = (v) => serialize(v, maxDepth, seen, depth + 1, budget);
|
|
1418
2165
|
seen.add(obj);
|
|
1419
2166
|
try {
|
|
1420
|
-
if (isReactElement(obj)) {
|
|
1421
|
-
const out2 = { $type: "element", name: getDisplayName(obj.type) };
|
|
2167
|
+
if ((0, import_diff3.isReactElement)(obj)) {
|
|
2168
|
+
const out2 = { $type: "element", name: (0, import_tracker.getDisplayName)(obj.type) };
|
|
1422
2169
|
if (obj.key !== null && obj.key !== void 0) out2.key = String(obj.key);
|
|
1423
|
-
out2.props =
|
|
2170
|
+
out2.props = next(obj.props);
|
|
1424
2171
|
return out2;
|
|
1425
2172
|
}
|
|
1426
2173
|
if (obj instanceof Date) return { $type: "Date", value: obj.toISOString() };
|
|
1427
2174
|
if (obj instanceof RegExp) return { $type: "RegExp", value: String(obj) };
|
|
2175
|
+
if (ArrayBuffer.isView(obj) || obj instanceof ArrayBuffer) {
|
|
2176
|
+
const bin = obj;
|
|
2177
|
+
return { $type: bin.constructor?.name || "ArrayBuffer", length: typeof bin.length === "number" ? bin.length : bin.byteLength };
|
|
2178
|
+
}
|
|
2179
|
+
if (obj instanceof Promise) return "[Promise]";
|
|
2180
|
+
if (typeof Node !== "undefined" && obj instanceof Node) return typeof Element !== "undefined" && obj instanceof Element ? `<${obj.tagName.toLowerCase()}>` : `[${obj.nodeName}]`;
|
|
2181
|
+
if (obj === globalThis) return "[Window]";
|
|
1428
2182
|
if (obj instanceof Map) {
|
|
1429
|
-
|
|
2183
|
+
const entries = [];
|
|
2184
|
+
for (const [k, v] of obj) {
|
|
2185
|
+
if (entries.length >= SERIALIZE_MAX_ENTRIES) {
|
|
2186
|
+
entries.push(["\u2026", `+${obj.size - SERIALIZE_MAX_ENTRIES} more`]);
|
|
2187
|
+
break;
|
|
2188
|
+
}
|
|
2189
|
+
entries.push([next(k), next(v)]);
|
|
2190
|
+
}
|
|
2191
|
+
return { $type: "Map", entries };
|
|
2192
|
+
}
|
|
2193
|
+
if (obj instanceof Set) {
|
|
2194
|
+
const values = [];
|
|
2195
|
+
for (const v of obj) {
|
|
2196
|
+
if (values.length >= SERIALIZE_MAX_ENTRIES) {
|
|
2197
|
+
values.push(`\u2026+${obj.size - SERIALIZE_MAX_ENTRIES} more`);
|
|
2198
|
+
break;
|
|
2199
|
+
}
|
|
2200
|
+
values.push(next(v));
|
|
2201
|
+
}
|
|
2202
|
+
return { $type: "Set", values };
|
|
2203
|
+
}
|
|
2204
|
+
if (Array.isArray(obj)) {
|
|
2205
|
+
const out2 = obj.slice(0, SERIALIZE_MAX_ENTRIES).map(next);
|
|
2206
|
+
if (obj.length > SERIALIZE_MAX_ENTRIES) out2.push(`\u2026+${obj.length - SERIALIZE_MAX_ENTRIES} more`);
|
|
2207
|
+
return out2;
|
|
1430
2208
|
}
|
|
1431
|
-
if (obj instanceof Set) return { $type: "Set", values: [...obj].map((v) => serialize(v, maxDepth, seen, depth + 1)) };
|
|
1432
|
-
if (Array.isArray(obj)) return obj.map((v) => serialize(v, maxDepth, seen, depth + 1));
|
|
1433
|
-
if (typeof Element !== "undefined" && obj instanceof Element) return `<${obj.tagName.toLowerCase()}>`;
|
|
1434
2209
|
const out = {};
|
|
1435
|
-
|
|
2210
|
+
const keys = Object.keys(obj);
|
|
2211
|
+
for (const k of keys.slice(0, SERIALIZE_MAX_ENTRIES)) out[k] = next(obj[k]);
|
|
2212
|
+
if (keys.length > SERIALIZE_MAX_ENTRIES) out["\u2026"] = `+${keys.length - SERIALIZE_MAX_ENTRIES} more`;
|
|
1436
2213
|
const proto = Object.getPrototypeOf(obj);
|
|
1437
2214
|
if (proto && proto !== Object.prototype && proto.constructor?.name) out.$type = proto.constructor.name;
|
|
1438
2215
|
return out;
|
|
@@ -1472,33 +2249,42 @@ ${formatFixes(reports)}`);
|
|
|
1472
2249
|
}
|
|
1473
2250
|
function createDevtoolsNotifier(options = {}) {
|
|
1474
2251
|
const bufferSize = options.bufferSize ?? 300;
|
|
1475
|
-
const maxDepth = options.maxDepth ??
|
|
2252
|
+
const maxDepth = options.maxDepth ?? 4;
|
|
1476
2253
|
const target = options.target ?? (typeof window !== "undefined" ? window : void 0);
|
|
1477
2254
|
const buffer = [];
|
|
1478
2255
|
let seq = 0;
|
|
1479
2256
|
let flashOn = options.flashAvoidable ?? false;
|
|
2257
|
+
let live = !target || typeof target.addEventListener !== "function";
|
|
2258
|
+
if (!live) {
|
|
2259
|
+
target.addEventListener("message", (event) => {
|
|
2260
|
+
const data = event.data;
|
|
2261
|
+
if ((event.source === target || !event.source) && data && data.__rerenderLensReady === true) live = true;
|
|
2262
|
+
});
|
|
2263
|
+
}
|
|
1480
2264
|
const post = (type, payload) => {
|
|
1481
|
-
if (!target) return;
|
|
2265
|
+
if (!target || type === "report" && !live) return;
|
|
1482
2266
|
const msg = { [DEVTOOLS_MARKER]: true, version: PROTOCOL_VERSION, type, payload };
|
|
1483
2267
|
target.postMessage(msg, "*");
|
|
1484
2268
|
};
|
|
1485
2269
|
const source = options.source ?? "page";
|
|
1486
2270
|
const info = () => ({
|
|
1487
2271
|
count: buffer.length,
|
|
1488
|
-
library: VERSION,
|
|
2272
|
+
library: import_version.VERSION,
|
|
1489
2273
|
protocol: PROTOCOL_VERSION,
|
|
1490
|
-
react: getRenderers(),
|
|
1491
|
-
production: isProductionReact(),
|
|
1492
|
-
enabled: isEnabled(),
|
|
1493
|
-
options: serializeOptions(getState().options),
|
|
2274
|
+
react: (0, import_fiber.getRenderers)(),
|
|
2275
|
+
production: (0, import_fiber.isProductionReact)(),
|
|
2276
|
+
enabled: (0, import_tracker.isEnabled)(),
|
|
2277
|
+
options: serializeOptions((0, import_state.getState)().options),
|
|
1494
2278
|
source,
|
|
1495
2279
|
injected: typeof window !== "undefined" && typeof window.__RERENDER_LENS_INJECTED__ === "string",
|
|
1496
|
-
scheduled: getState().scheduled,
|
|
1497
|
-
commits: getState().commits,
|
|
1498
|
-
overhead: { totalMs: getState().overheadMs, maxCommitMs: getState().maxCommitMs }
|
|
2280
|
+
scheduled: (0, import_state.getState)().scheduled,
|
|
2281
|
+
commits: (0, import_state.getState)().commits,
|
|
2282
|
+
overhead: { totalMs: (0, import_state.getState)().overheadMs, maxCommitMs: (0, import_state.getState)().maxCommitMs },
|
|
2283
|
+
truncated: (0, import_state.getState)().truncated
|
|
1499
2284
|
});
|
|
1500
2285
|
const bridge = {
|
|
1501
2286
|
replay: () => {
|
|
2287
|
+
live = true;
|
|
1502
2288
|
post("hello", info());
|
|
1503
2289
|
for (const e of buffer) post("report", e.payload);
|
|
1504
2290
|
},
|
|
@@ -1510,7 +2296,7 @@ ${formatFixes(reports)}`);
|
|
|
1510
2296
|
return buffer.length;
|
|
1511
2297
|
},
|
|
1512
2298
|
version: PROTOCOL_VERSION,
|
|
1513
|
-
library: VERSION,
|
|
2299
|
+
library: import_version.VERSION,
|
|
1514
2300
|
info,
|
|
1515
2301
|
pull: (since = 0) => {
|
|
1516
2302
|
const first = buffer[0];
|
|
@@ -1519,41 +2305,41 @@ ${formatFixes(reports)}`);
|
|
|
1519
2305
|
return { seq, reports, dropped };
|
|
1520
2306
|
},
|
|
1521
2307
|
configure: (next) => {
|
|
1522
|
-
configure(deserializeOptions(next ?? {}));
|
|
1523
|
-
return serializeOptions(getState().options);
|
|
2308
|
+
(0, import_tracker.configure)(deserializeOptions(next ?? {}));
|
|
2309
|
+
return serializeOptions((0, import_state.getState)().options);
|
|
1524
2310
|
},
|
|
1525
|
-
getOptions: () => serializeOptions(getState().options),
|
|
2311
|
+
getOptions: () => serializeOptions((0, import_state.getState)().options),
|
|
1526
2312
|
highlight: (id) => {
|
|
1527
2313
|
if (id === null || id === void 0) {
|
|
1528
|
-
clearHighlight();
|
|
2314
|
+
(0, import_overlay.clearHighlight)();
|
|
1529
2315
|
return true;
|
|
1530
2316
|
}
|
|
1531
|
-
const fiber = fiberById(id);
|
|
2317
|
+
const fiber = (0, import_fiber.fiberById)(id);
|
|
1532
2318
|
if (!fiber) {
|
|
1533
|
-
clearHighlight();
|
|
2319
|
+
(0, import_overlay.clearHighlight)();
|
|
1534
2320
|
return false;
|
|
1535
2321
|
}
|
|
1536
|
-
const nodes = hostNodesOf(fiber);
|
|
1537
|
-
highlight({ nodes, label: fiberName(fiber) });
|
|
2322
|
+
const nodes = (0, import_fiber.hostNodesOf)(fiber);
|
|
2323
|
+
(0, import_overlay.highlight)({ nodes, label: (0, import_fiber.fiberName)(fiber) });
|
|
1538
2324
|
return nodes.length > 0;
|
|
1539
2325
|
},
|
|
1540
2326
|
flashAvoidable: (on) => {
|
|
1541
2327
|
flashOn = !!on;
|
|
1542
2328
|
},
|
|
1543
2329
|
inspect: (node) => {
|
|
1544
|
-
const comp = nearestComponent(fiberForNode(node));
|
|
2330
|
+
const comp = (0, import_fiber.nearestComponent)((0, import_fiber.fiberForNode)(node));
|
|
1545
2331
|
if (!comp) return null;
|
|
1546
|
-
const id = instanceIdOf(comp) ?? null;
|
|
2332
|
+
const id = (0, import_fiber.instanceIdOf)(comp) ?? null;
|
|
1547
2333
|
const path = [];
|
|
1548
2334
|
let f = comp.return;
|
|
1549
2335
|
while (f) {
|
|
1550
|
-
if (f.tag === 0 || f.tag === 1 || f.tag === 11 || f.tag === 14 || f.tag === 15) path.unshift(fiberName(f));
|
|
2336
|
+
if (f.tag === 0 || f.tag === 1 || f.tag === 11 || f.tag === 14 || f.tag === 15) path.unshift((0, import_fiber.fiberName)(f));
|
|
1551
2337
|
f = f.return;
|
|
1552
2338
|
}
|
|
1553
2339
|
return {
|
|
1554
|
-
component: fiberName(comp),
|
|
2340
|
+
component: (0, import_fiber.fiberName)(comp),
|
|
1555
2341
|
instanceId: id,
|
|
1556
|
-
tracked: shouldTrack(fiberType(comp), getState().options),
|
|
2342
|
+
tracked: (0, import_tracker.shouldTrack)((0, import_fiber.fiberType)(comp), (0, import_state.getState)().options),
|
|
1557
2343
|
path,
|
|
1558
2344
|
reports: id === null ? [] : buffer.filter((e) => e.instanceId === id).slice(-20).map((e) => e.payload)
|
|
1559
2345
|
};
|
|
@@ -1681,37 +2467,14 @@ ${formatFixes(reports)}`);
|
|
|
1681
2467
|
if (buffer.length > bufferSize) buffer.splice(0, buffer.length - bufferSize);
|
|
1682
2468
|
postAll("report", payload);
|
|
1683
2469
|
if (flashOn && report.avoidable && report.instanceId) {
|
|
1684
|
-
const fiber = fiberById(report.instanceId);
|
|
1685
|
-
if (fiber) flash({ nodes: hostNodesOf(fiber), label: report.component });
|
|
2470
|
+
const fiber = (0, import_fiber.fiberById)(report.instanceId);
|
|
2471
|
+
if (fiber) (0, import_overlay.flash)({ nodes: (0, import_fiber.hostNodesOf)(fiber), label: report.component });
|
|
1686
2472
|
}
|
|
1687
2473
|
};
|
|
1688
2474
|
}
|
|
1689
2475
|
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
exports.classify = classify;
|
|
1696
|
-
exports.combineNotifiers = combineNotifiers;
|
|
1697
|
-
exports.configure = configure;
|
|
1698
|
-
exports.createCollector = createCollector;
|
|
1699
|
-
exports.createDevtoolsNotifier = createDevtoolsNotifier;
|
|
1700
|
-
exports.deepEqual = deepEqual;
|
|
1701
|
-
exports.diffRecords = diffRecords;
|
|
1702
|
-
exports.disable = disable;
|
|
1703
|
-
exports.ensureDevtoolsHook = ensureDevtoolsHook;
|
|
1704
|
-
exports.getDisplayName = getDisplayName;
|
|
1705
|
-
exports.getRenderers = getRenderers;
|
|
1706
|
-
exports.init = init;
|
|
1707
|
-
exports.isEnabled = isEnabled;
|
|
1708
|
-
exports.isProductionReact = isProductionReact;
|
|
1709
|
-
exports.printReport = printReport;
|
|
1710
|
-
exports.serialize = serialize;
|
|
1711
|
-
exports.shouldTrack = shouldTrack;
|
|
1712
|
-
exports.summarize = summarize;
|
|
1713
|
-
exports.track = track;
|
|
1714
|
-
|
|
1715
|
-
return exports;
|
|
1716
|
-
|
|
1717
|
-
})({});
|
|
2476
|
+
// src/inject.ts
|
|
2477
|
+
var import_version2 = __toESM(require_version(), 1);
|
|
2478
|
+
return __toCommonJS(inject_exports);
|
|
2479
|
+
})();
|
|
2480
|
+
globalThis.RerenderLens = RerenderLens;
|