rerender-lens 0.1.0 → 0.3.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 +164 -6
- package/README.md +298 -75
- package/dist/budget-COBu7jBU.d.cts +64 -0
- package/dist/budget-LkNjGtRc.d.ts +64 -0
- package/dist/cli.cjs +458 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +4 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.js +452 -0
- package/dist/cli.js.map +1 -0
- package/dist/devtools-BHGUUo-p.d.ts +244 -0
- package/dist/devtools-DmhWiWcN.d.cts +244 -0
- package/dist/index.cjs +1686 -74
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +67 -153
- package/dist/index.d.ts +67 -153
- package/dist/index.js +1643 -13
- package/dist/index.js.map +1 -1
- package/dist/notifiers-BGQtWKfX.d.cts +90 -0
- package/dist/notifiers-BjjGSHpp.d.ts +90 -0
- package/dist/playwright.cjs +196 -0
- package/dist/playwright.cjs.map +1 -0
- package/dist/playwright.d.cts +35 -0
- package/dist/playwright.d.ts +35 -0
- package/dist/playwright.js +184 -0
- package/dist/playwright.js.map +1 -0
- package/dist/relay.cjs +166 -0
- package/dist/relay.cjs.map +1 -0
- package/dist/relay.d.cts +41 -0
- package/dist/relay.d.ts +41 -0
- package/dist/relay.js +161 -0
- package/dist/relay.js.map +1 -0
- package/dist/rerender-lens.iife.js +1717 -0
- package/dist/setup.cjs +1510 -0
- package/dist/setup.cjs.map +1 -0
- package/dist/setup.d.cts +2 -0
- package/dist/setup.d.ts +2 -0
- package/dist/setup.js +1508 -0
- package/dist/setup.js.map +1 -0
- package/dist/types-BzUEVkxJ.d.cts +177 -0
- package/dist/types-BzUEVkxJ.d.ts +177 -0
- package/dist/vite.cjs +113 -0
- package/dist/vite.cjs.map +1 -0
- package/dist/vite.d.cts +84 -0
- package/dist/vite.d.ts +84 -0
- package/dist/vite.js +103 -0
- package/dist/vite.js.map +1 -0
- package/dist/vitest-setup.cjs +1299 -0
- package/dist/vitest-setup.cjs.map +1 -0
- package/dist/vitest-setup.d.cts +8 -0
- package/dist/vitest-setup.d.ts +8 -0
- package/dist/vitest-setup.js +1297 -0
- package/dist/vitest-setup.js.map +1 -0
- package/dist/vitest.cjs +1360 -0
- package/dist/vitest.cjs.map +1 -0
- package/dist/vitest.d.cts +52 -0
- package/dist/vitest.d.ts +52 -0
- package/dist/vitest.js +1351 -0
- package/dist/vitest.js.map +1 -0
- package/package.json +83 -17
- package/panel/panel.css +418 -0
- package/panel/panel.html +12 -0
- package/panel/panel.js +3325 -0
- package/dist/chunk-3YHI7BCU.js +0 -544
- package/dist/chunk-3YHI7BCU.js.map +0 -1
- package/dist/chunk-DOYB4MKH.cjs +0 -562
- package/dist/chunk-DOYB4MKH.cjs.map +0 -1
- package/dist/jsx-dev-runtime.cjs +0 -32
- package/dist/jsx-dev-runtime.cjs.map +0 -1
- package/dist/jsx-dev-runtime.d.cts +0 -8
- package/dist/jsx-dev-runtime.d.ts +0 -8
- package/dist/jsx-dev-runtime.js +0 -9
- package/dist/jsx-dev-runtime.js.map +0 -1
- package/dist/jsx-runtime.cjs +0 -34
- package/dist/jsx-runtime.cjs.map +0 -1
- package/dist/jsx-runtime.d.cts +0 -9
- package/dist/jsx-runtime.d.ts +0 -9
- package/dist/jsx-runtime.js +0 -10
- package/dist/jsx-runtime.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,110 +1,22 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { O as Options, C as ChangeKind, a as Change, H as HookChange, b as HookSnapshot, P as ParentInfo, c as CommitPriority, S as SourceLocation, d as CommitCause, R as RenderReport } from './types-BzUEVkxJ.cjs';
|
|
2
|
+
export { e as ComponentMatcher, M as MARKER, N as Notifier, f as RenderTrigger } from './types-BzUEVkxJ.cjs';
|
|
3
|
+
import { F as Fiber } from './devtools-DmhWiWcN.cjs';
|
|
4
|
+
export { C as ChannelCommand, a as ChannelReply, D as DEFAULT_CHANNEL, b as DEVTOOLS_MARKER, c as DevtoolsBridge, d as DevtoolsMessage, e as DevtoolsNotifierOptions, H as HelloPayload, I as InspectResult, P as PROTOCOL_VERSION, f as PullResult, R as RendererInfo, S as SerializableOptions, g as createDevtoolsNotifier, h as deserializeOptions, i as ensureDevtoolsHook, j as getRenderers, k as isProductionReact, s as serialize, l as serializeOptions } from './devtools-DmhWiWcN.cjs';
|
|
5
|
+
export { B as Budget, a as BudgetResult, b as BudgetViolation, F as Fix, d as FixKind, R as RankedFix, e as assertWithinBudget, g as avoidableCounts, c as checkBudget, h as fixKey, i as fixesFor, f as formatFixes, r as rankFixes, t as toBudget } from './budget-COBu7jBU.cjs';
|
|
6
|
+
export { C as Collector, a as CompareRow, b as Comparison, S as SessionSummary, c as combineNotifiers, d as compareSummaries, e as createCollector, f as formatComparison, p as parseExport, s as summarizeReports } from './notifiers-BGQtWKfX.cjs';
|
|
2
7
|
|
|
3
|
-
/** Why a single prop/state/hook value differs between two renders. */
|
|
4
|
-
type ChangeKind =
|
|
5
|
-
/** New reference, but deep-equal to the previous value. Avoidable. */
|
|
6
|
-
'deep-equal'
|
|
7
|
-
/** A new function with the same name/body shape. Almost always avoidable. */
|
|
8
|
-
| 'function'
|
|
9
|
-
/** A new React element that renders the same type with deep-equal props. Avoidable. */
|
|
10
|
-
| 'element'
|
|
11
|
-
/** The value genuinely changed. */
|
|
12
|
-
| 'different'
|
|
13
|
-
/** Key was added. */
|
|
14
|
-
| 'added'
|
|
15
|
-
/** Key was removed. */
|
|
16
|
-
| 'removed';
|
|
17
|
-
interface Change {
|
|
18
|
-
/** Dot path from the root, e.g. `style.color` or `items[2]`. */
|
|
19
|
-
path: string;
|
|
20
|
-
kind: ChangeKind;
|
|
21
|
-
prev: unknown;
|
|
22
|
-
next: unknown;
|
|
23
|
-
}
|
|
24
|
-
/** What caused a re-render. */
|
|
25
|
-
type RenderTrigger =
|
|
26
|
-
/** At least one prop genuinely changed. */
|
|
27
|
-
'props'
|
|
28
|
-
/** Props are equal by value, but the parent re-rendered. Wrap in React.memo. */
|
|
29
|
-
| 'parent'
|
|
30
|
-
/** Own state (useState/useReducer/this.setState) changed. */
|
|
31
|
-
| 'state'
|
|
32
|
-
/** A non-state hook value (useContext, useSyncExternalStore) changed. */
|
|
33
|
-
| 'hooks'
|
|
34
|
-
/** More than one of the above. */
|
|
35
|
-
| 'mixed';
|
|
36
|
-
interface HookChange extends Change {
|
|
37
|
-
/** `useState`, `useReducer`, `useContext`, ... */
|
|
38
|
-
hook: string;
|
|
39
|
-
/** Position of the hook in call order (0-based). */
|
|
40
|
-
index: number;
|
|
41
|
-
}
|
|
42
|
-
interface RenderReport {
|
|
43
|
-
/** Display name of the tracked component. */
|
|
44
|
-
component: string;
|
|
45
|
-
/** Monotonic per-component render count (1 = first update, mount is never reported). */
|
|
46
|
-
renderCount: number;
|
|
47
|
-
trigger: RenderTrigger;
|
|
48
|
-
/** True when the re-render produced no genuine change in props, state, or hooks. */
|
|
49
|
-
avoidable: boolean;
|
|
50
|
-
props: {
|
|
51
|
-
prev: Record<string, unknown>;
|
|
52
|
-
next: Record<string, unknown>;
|
|
53
|
-
};
|
|
54
|
-
propChanges: Change[];
|
|
55
|
-
/** Class components only. */
|
|
56
|
-
stateChanges: Change[];
|
|
57
|
-
/** Function components only, when `trackHooks` is on. */
|
|
58
|
-
hookChanges: HookChange[];
|
|
59
|
-
/** Human-readable explanations and suggested fixes. */
|
|
60
|
-
reasons: string[];
|
|
61
|
-
/** `performance.now()` (or `Date.now()`) when the report was produced. */
|
|
62
|
-
time: number;
|
|
63
|
-
}
|
|
64
|
-
type Notifier = (report: RenderReport) => void;
|
|
65
|
-
type ComponentMatcher = string | RegExp | ((displayName: string) => boolean);
|
|
66
|
-
interface Options {
|
|
67
|
-
/** Track every `React.memo`-wrapped component and every `PureComponent`. Default false. */
|
|
68
|
-
trackAllMemoized?: boolean;
|
|
69
|
-
/** Track every component, memoized or not. Noisy. Default false. */
|
|
70
|
-
trackAllComponents?: boolean;
|
|
71
|
-
/** Components to track by display name (string = exact match). */
|
|
72
|
-
include?: ComponentMatcher[];
|
|
73
|
-
/** Components never to track, even when marked. */
|
|
74
|
-
exclude?: ComponentMatcher[];
|
|
75
|
-
/** Capture `useState`/`useReducer`/`useContext` values and diff them. Default true. */
|
|
76
|
-
trackHooks?: boolean;
|
|
77
|
-
/** Report re-renders caused by genuine changes too, not only avoidable ones. Default false. */
|
|
78
|
-
logAll?: boolean;
|
|
79
|
-
/** Do not print to the console. Reports still reach `notifier`. Default false. */
|
|
80
|
-
silent?: boolean;
|
|
81
|
-
/** Receive every report. Combine several with `combineNotifiers`. */
|
|
82
|
-
notifier?: Notifier;
|
|
83
|
-
/** Use `console.groupCollapsed` instead of `console.group`. Default true. */
|
|
84
|
-
collapse?: boolean;
|
|
85
|
-
/** Console-like sink used for printing. Default `console`. */
|
|
86
|
-
console?: Pick<Console, 'log' | 'group' | 'groupCollapsed' | 'groupEnd' | 'warn'>;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* The React object to patch. Structural so that both `import React from 'react'`
|
|
90
|
-
* and `import * as React from 'react'` type-check.
|
|
91
|
-
*/
|
|
92
|
-
type ReactLike = Pick<typeof ReactNS, 'createElement' | 'memo' | 'forwardRef' | 'useRef'> & Partial<Pick<typeof ReactNS, 'useState' | 'useReducer' | 'useContext' | 'useSyncExternalStore'>>;
|
|
93
|
-
/** Marker static: `MyComponent.rerenderLens = true` opts a component in. */
|
|
94
|
-
declare const MARKER: "rerenderLens";
|
|
95
|
-
|
|
96
|
-
type AnyType = any;
|
|
97
8
|
declare function getDisplayName(type: unknown): string;
|
|
98
|
-
/**
|
|
99
|
-
declare function
|
|
9
|
+
/** Decide whether a component type is tracked under the given options. */
|
|
10
|
+
declare function shouldTrack(type: unknown, o: Options): boolean;
|
|
100
11
|
/**
|
|
101
|
-
*
|
|
102
|
-
*
|
|
12
|
+
* Start reporting re-renders of tracked components. Observes React commits
|
|
13
|
+
* through the DevTools global hook; nothing in React is patched or wrapped.
|
|
14
|
+
* Returns a function that stops reporting.
|
|
103
15
|
*/
|
|
104
|
-
declare function init(
|
|
105
|
-
/**
|
|
16
|
+
declare function init(options?: Options): () => void;
|
|
17
|
+
/** Merge options at runtime. Takes effect on the next commit. */
|
|
106
18
|
declare function configure(options: Options): void;
|
|
107
|
-
/**
|
|
19
|
+
/** Stop reporting and restore the DevTools hook callback. */
|
|
108
20
|
declare function disable(): void;
|
|
109
21
|
declare function isEnabled(): boolean;
|
|
110
22
|
/**
|
|
@@ -113,6 +25,27 @@ declare function isEnabled(): boolean;
|
|
|
113
25
|
*/
|
|
114
26
|
declare function track<T>(component: T, name?: string): T;
|
|
115
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Custom hook names, opt-in (`resolveHookNames`). React keeps no record of which custom hook
|
|
30
|
+
* called a primitive, so, like React DevTools, we re-run the component once with a stand-in
|
|
31
|
+
* dispatcher: every primitive records the call stack, and the frames between the primitive and the
|
|
32
|
+
* component are the custom hooks. Values come from the fiber's real hook nodes so the component
|
|
33
|
+
* takes the same code path. Results are cached per component type; a throwing render yields no names.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/** `currentDispatcherRef` as react-dom injects it: `{ current }` (React 16-18) or the shared internals `{ H }` (React 19). */
|
|
37
|
+
type DispatcherRef = {
|
|
38
|
+
current?: unknown;
|
|
39
|
+
H?: unknown;
|
|
40
|
+
};
|
|
41
|
+
/** Function names in the frames between our dispatcher and the component (innermost first). */
|
|
42
|
+
declare function customHooksFromStack(stack: string, componentName: string, marker: string): string[];
|
|
43
|
+
/**
|
|
44
|
+
* Custom hook chain per hook node index for a rendered function-component fiber. Empty map when the
|
|
45
|
+
* replay fails, when the dispatcher ref is missing, or when the node count does not match.
|
|
46
|
+
*/
|
|
47
|
+
declare function resolveHookNames(fiber: Fiber, ref: DispatcherRef | null | undefined): Map<number, string[]>;
|
|
48
|
+
|
|
116
49
|
type HookOptions = Pick<Options, 'notifier' | 'silent' | 'console' | 'collapse' | 'logAll'>;
|
|
117
50
|
/**
|
|
118
51
|
* Track one component from the inside, without patching React:
|
|
@@ -147,67 +80,48 @@ declare function diffRecords(prev: Record<string, unknown> | undefined | null, n
|
|
|
147
80
|
|
|
148
81
|
interface BuildInput {
|
|
149
82
|
component: string;
|
|
83
|
+
instanceId?: number;
|
|
150
84
|
renderCount: number;
|
|
151
85
|
prevProps: Record<string, unknown>;
|
|
152
86
|
nextProps: Record<string, unknown>;
|
|
153
87
|
propChanges: Change[];
|
|
154
88
|
stateChanges?: Change[];
|
|
155
89
|
hookChanges?: HookChange[];
|
|
90
|
+
hookState?: HookSnapshot[];
|
|
91
|
+
contexts?: {
|
|
92
|
+
name: string;
|
|
93
|
+
value: unknown;
|
|
94
|
+
}[];
|
|
95
|
+
state?: Record<string, unknown>;
|
|
96
|
+
parent?: ParentInfo | null;
|
|
97
|
+
owner?: string | null;
|
|
98
|
+
path?: string[];
|
|
99
|
+
/** Default true: `useWhyRerender` and the console output assume the component decides on props alone. */
|
|
100
|
+
memoized?: boolean;
|
|
101
|
+
selfDuration?: number;
|
|
102
|
+
treeDuration?: number;
|
|
103
|
+
commitId?: number;
|
|
104
|
+
commitPriority?: CommitPriority;
|
|
105
|
+
source?: SourceLocation;
|
|
106
|
+
updaters?: string[];
|
|
107
|
+
commitCause?: CommitCause;
|
|
108
|
+
afterCommit?: number;
|
|
109
|
+
key?: string | null;
|
|
156
110
|
}
|
|
111
|
+
/** `useCart › useState#0` when custom hook names are known, else `useState #0`. */
|
|
112
|
+
declare const hookLabel: (c: {
|
|
113
|
+
hook: string;
|
|
114
|
+
index: number;
|
|
115
|
+
custom?: string[];
|
|
116
|
+
}) => string;
|
|
117
|
+
/** Store-specific advice for a `useSyncExternalStore` snapshot that is a new reference with equal contents. */
|
|
118
|
+
declare function storeAdvice(custom: string[] | undefined): string;
|
|
157
119
|
declare function buildReport(input: BuildInput): RenderReport;
|
|
158
120
|
declare function summarize(report: RenderReport): string;
|
|
159
121
|
/** Default notifier: prints a console group per report. */
|
|
160
122
|
declare function printReport(report: RenderReport, options: Options): void;
|
|
161
123
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
readonly reports: RenderReport[];
|
|
165
|
-
/** Reports where `avoidable` is true. */
|
|
166
|
-
readonly avoidable: RenderReport[];
|
|
167
|
-
/** Pass this to `init({ notifier })`. */
|
|
168
|
-
readonly notifier: Notifier;
|
|
169
|
-
clear(): void;
|
|
170
|
-
/** Throws with a readable message if any avoidable re-render was recorded. */
|
|
171
|
-
assertNoAvoidable(): void;
|
|
172
|
-
}
|
|
173
|
-
/** Collect reports in memory. Meant for tests. */
|
|
174
|
-
declare function createCollector(): Collector;
|
|
175
|
-
declare function combineNotifiers(...notifiers: Array<Notifier | undefined | null | false>): Notifier;
|
|
176
|
-
|
|
177
|
-
declare const DEVTOOLS_MARKER: "__rerenderLens";
|
|
178
|
-
declare const PROTOCOL_VERSION = 1;
|
|
179
|
-
interface DevtoolsMessage {
|
|
180
|
-
[DEVTOOLS_MARKER]: true;
|
|
181
|
-
version: number;
|
|
182
|
-
type: 'report' | 'clear' | 'hello';
|
|
183
|
-
payload?: unknown;
|
|
184
|
-
}
|
|
185
|
-
interface DevtoolsNotifierOptions {
|
|
186
|
-
/** How many reports to keep for `replay()`. Default 300. */
|
|
187
|
-
bufferSize?: number;
|
|
188
|
-
/** Where to post. Default `window`. */
|
|
189
|
-
target?: Pick<Window, 'postMessage'>;
|
|
190
|
-
/** Max serialization depth. Default 6. */
|
|
191
|
-
maxDepth?: number;
|
|
192
|
-
}
|
|
193
|
-
interface DevtoolsBridge {
|
|
194
|
-
/** Re-post every buffered report (a panel that opened late calls this). */
|
|
195
|
-
replay(): void;
|
|
196
|
-
clear(): void;
|
|
197
|
-
readonly size: number;
|
|
198
|
-
readonly version: number;
|
|
199
|
-
}
|
|
200
|
-
declare global {
|
|
201
|
-
interface Window {
|
|
202
|
-
__RERENDER_LENS_DEVTOOLS__?: DevtoolsBridge;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
/** Convert a report into a structured-clone-safe value (functions, elements, cycles removed). */
|
|
206
|
-
declare function serialize(value: unknown, maxDepth?: number, seen?: WeakSet<object>, depth?: number): unknown;
|
|
207
|
-
/**
|
|
208
|
-
* A notifier that posts every report on `window` for a DevTools extension to pick up.
|
|
209
|
-
* Also installs `window.__RERENDER_LENS_DEVTOOLS__` with `replay()` / `clear()`.
|
|
210
|
-
*/
|
|
211
|
-
declare function createDevtoolsNotifier(options?: DevtoolsNotifierOptions): Notifier;
|
|
124
|
+
/** Library version, injected by the build; "dev" when running from source. */
|
|
125
|
+
declare const VERSION: string;
|
|
212
126
|
|
|
213
|
-
export {
|
|
127
|
+
export { Change, ChangeKind, CommitCause, CommitPriority, type DispatcherRef, HookChange, HookSnapshot, Options, ParentInfo, RenderReport, SourceLocation, VERSION, buildReport, classify, configure, customHooksFromStack, deepEqual, diffRecords, disable, getDisplayName, hookLabel, init, isEnabled, printReport, resolveHookNames, shouldTrack, storeAdvice, summarize, track, useWhyRerender };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,110 +1,22 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { O as Options, C as ChangeKind, a as Change, H as HookChange, b as HookSnapshot, P as ParentInfo, c as CommitPriority, S as SourceLocation, d as CommitCause, R as RenderReport } from './types-BzUEVkxJ.js';
|
|
2
|
+
export { e as ComponentMatcher, M as MARKER, N as Notifier, f as RenderTrigger } from './types-BzUEVkxJ.js';
|
|
3
|
+
import { F as Fiber } from './devtools-BHGUUo-p.js';
|
|
4
|
+
export { C as ChannelCommand, a as ChannelReply, D as DEFAULT_CHANNEL, b as DEVTOOLS_MARKER, c as DevtoolsBridge, d as DevtoolsMessage, e as DevtoolsNotifierOptions, H as HelloPayload, I as InspectResult, P as PROTOCOL_VERSION, f as PullResult, R as RendererInfo, S as SerializableOptions, g as createDevtoolsNotifier, h as deserializeOptions, i as ensureDevtoolsHook, j as getRenderers, k as isProductionReact, s as serialize, l as serializeOptions } from './devtools-BHGUUo-p.js';
|
|
5
|
+
export { B as Budget, a as BudgetResult, b as BudgetViolation, F as Fix, d as FixKind, R as RankedFix, e as assertWithinBudget, g as avoidableCounts, c as checkBudget, h as fixKey, i as fixesFor, f as formatFixes, r as rankFixes, t as toBudget } from './budget-LkNjGtRc.js';
|
|
6
|
+
export { C as Collector, a as CompareRow, b as Comparison, S as SessionSummary, c as combineNotifiers, d as compareSummaries, e as createCollector, f as formatComparison, p as parseExport, s as summarizeReports } from './notifiers-BjjGSHpp.js';
|
|
2
7
|
|
|
3
|
-
/** Why a single prop/state/hook value differs between two renders. */
|
|
4
|
-
type ChangeKind =
|
|
5
|
-
/** New reference, but deep-equal to the previous value. Avoidable. */
|
|
6
|
-
'deep-equal'
|
|
7
|
-
/** A new function with the same name/body shape. Almost always avoidable. */
|
|
8
|
-
| 'function'
|
|
9
|
-
/** A new React element that renders the same type with deep-equal props. Avoidable. */
|
|
10
|
-
| 'element'
|
|
11
|
-
/** The value genuinely changed. */
|
|
12
|
-
| 'different'
|
|
13
|
-
/** Key was added. */
|
|
14
|
-
| 'added'
|
|
15
|
-
/** Key was removed. */
|
|
16
|
-
| 'removed';
|
|
17
|
-
interface Change {
|
|
18
|
-
/** Dot path from the root, e.g. `style.color` or `items[2]`. */
|
|
19
|
-
path: string;
|
|
20
|
-
kind: ChangeKind;
|
|
21
|
-
prev: unknown;
|
|
22
|
-
next: unknown;
|
|
23
|
-
}
|
|
24
|
-
/** What caused a re-render. */
|
|
25
|
-
type RenderTrigger =
|
|
26
|
-
/** At least one prop genuinely changed. */
|
|
27
|
-
'props'
|
|
28
|
-
/** Props are equal by value, but the parent re-rendered. Wrap in React.memo. */
|
|
29
|
-
| 'parent'
|
|
30
|
-
/** Own state (useState/useReducer/this.setState) changed. */
|
|
31
|
-
| 'state'
|
|
32
|
-
/** A non-state hook value (useContext, useSyncExternalStore) changed. */
|
|
33
|
-
| 'hooks'
|
|
34
|
-
/** More than one of the above. */
|
|
35
|
-
| 'mixed';
|
|
36
|
-
interface HookChange extends Change {
|
|
37
|
-
/** `useState`, `useReducer`, `useContext`, ... */
|
|
38
|
-
hook: string;
|
|
39
|
-
/** Position of the hook in call order (0-based). */
|
|
40
|
-
index: number;
|
|
41
|
-
}
|
|
42
|
-
interface RenderReport {
|
|
43
|
-
/** Display name of the tracked component. */
|
|
44
|
-
component: string;
|
|
45
|
-
/** Monotonic per-component render count (1 = first update, mount is never reported). */
|
|
46
|
-
renderCount: number;
|
|
47
|
-
trigger: RenderTrigger;
|
|
48
|
-
/** True when the re-render produced no genuine change in props, state, or hooks. */
|
|
49
|
-
avoidable: boolean;
|
|
50
|
-
props: {
|
|
51
|
-
prev: Record<string, unknown>;
|
|
52
|
-
next: Record<string, unknown>;
|
|
53
|
-
};
|
|
54
|
-
propChanges: Change[];
|
|
55
|
-
/** Class components only. */
|
|
56
|
-
stateChanges: Change[];
|
|
57
|
-
/** Function components only, when `trackHooks` is on. */
|
|
58
|
-
hookChanges: HookChange[];
|
|
59
|
-
/** Human-readable explanations and suggested fixes. */
|
|
60
|
-
reasons: string[];
|
|
61
|
-
/** `performance.now()` (or `Date.now()`) when the report was produced. */
|
|
62
|
-
time: number;
|
|
63
|
-
}
|
|
64
|
-
type Notifier = (report: RenderReport) => void;
|
|
65
|
-
type ComponentMatcher = string | RegExp | ((displayName: string) => boolean);
|
|
66
|
-
interface Options {
|
|
67
|
-
/** Track every `React.memo`-wrapped component and every `PureComponent`. Default false. */
|
|
68
|
-
trackAllMemoized?: boolean;
|
|
69
|
-
/** Track every component, memoized or not. Noisy. Default false. */
|
|
70
|
-
trackAllComponents?: boolean;
|
|
71
|
-
/** Components to track by display name (string = exact match). */
|
|
72
|
-
include?: ComponentMatcher[];
|
|
73
|
-
/** Components never to track, even when marked. */
|
|
74
|
-
exclude?: ComponentMatcher[];
|
|
75
|
-
/** Capture `useState`/`useReducer`/`useContext` values and diff them. Default true. */
|
|
76
|
-
trackHooks?: boolean;
|
|
77
|
-
/** Report re-renders caused by genuine changes too, not only avoidable ones. Default false. */
|
|
78
|
-
logAll?: boolean;
|
|
79
|
-
/** Do not print to the console. Reports still reach `notifier`. Default false. */
|
|
80
|
-
silent?: boolean;
|
|
81
|
-
/** Receive every report. Combine several with `combineNotifiers`. */
|
|
82
|
-
notifier?: Notifier;
|
|
83
|
-
/** Use `console.groupCollapsed` instead of `console.group`. Default true. */
|
|
84
|
-
collapse?: boolean;
|
|
85
|
-
/** Console-like sink used for printing. Default `console`. */
|
|
86
|
-
console?: Pick<Console, 'log' | 'group' | 'groupCollapsed' | 'groupEnd' | 'warn'>;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* The React object to patch. Structural so that both `import React from 'react'`
|
|
90
|
-
* and `import * as React from 'react'` type-check.
|
|
91
|
-
*/
|
|
92
|
-
type ReactLike = Pick<typeof ReactNS, 'createElement' | 'memo' | 'forwardRef' | 'useRef'> & Partial<Pick<typeof ReactNS, 'useState' | 'useReducer' | 'useContext' | 'useSyncExternalStore'>>;
|
|
93
|
-
/** Marker static: `MyComponent.rerenderLens = true` opts a component in. */
|
|
94
|
-
declare const MARKER: "rerenderLens";
|
|
95
|
-
|
|
96
|
-
type AnyType = any;
|
|
97
8
|
declare function getDisplayName(type: unknown): string;
|
|
98
|
-
/**
|
|
99
|
-
declare function
|
|
9
|
+
/** Decide whether a component type is tracked under the given options. */
|
|
10
|
+
declare function shouldTrack(type: unknown, o: Options): boolean;
|
|
100
11
|
/**
|
|
101
|
-
*
|
|
102
|
-
*
|
|
12
|
+
* Start reporting re-renders of tracked components. Observes React commits
|
|
13
|
+
* through the DevTools global hook; nothing in React is patched or wrapped.
|
|
14
|
+
* Returns a function that stops reporting.
|
|
103
15
|
*/
|
|
104
|
-
declare function init(
|
|
105
|
-
/**
|
|
16
|
+
declare function init(options?: Options): () => void;
|
|
17
|
+
/** Merge options at runtime. Takes effect on the next commit. */
|
|
106
18
|
declare function configure(options: Options): void;
|
|
107
|
-
/**
|
|
19
|
+
/** Stop reporting and restore the DevTools hook callback. */
|
|
108
20
|
declare function disable(): void;
|
|
109
21
|
declare function isEnabled(): boolean;
|
|
110
22
|
/**
|
|
@@ -113,6 +25,27 @@ declare function isEnabled(): boolean;
|
|
|
113
25
|
*/
|
|
114
26
|
declare function track<T>(component: T, name?: string): T;
|
|
115
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Custom hook names, opt-in (`resolveHookNames`). React keeps no record of which custom hook
|
|
30
|
+
* called a primitive, so, like React DevTools, we re-run the component once with a stand-in
|
|
31
|
+
* dispatcher: every primitive records the call stack, and the frames between the primitive and the
|
|
32
|
+
* component are the custom hooks. Values come from the fiber's real hook nodes so the component
|
|
33
|
+
* takes the same code path. Results are cached per component type; a throwing render yields no names.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/** `currentDispatcherRef` as react-dom injects it: `{ current }` (React 16-18) or the shared internals `{ H }` (React 19). */
|
|
37
|
+
type DispatcherRef = {
|
|
38
|
+
current?: unknown;
|
|
39
|
+
H?: unknown;
|
|
40
|
+
};
|
|
41
|
+
/** Function names in the frames between our dispatcher and the component (innermost first). */
|
|
42
|
+
declare function customHooksFromStack(stack: string, componentName: string, marker: string): string[];
|
|
43
|
+
/**
|
|
44
|
+
* Custom hook chain per hook node index for a rendered function-component fiber. Empty map when the
|
|
45
|
+
* replay fails, when the dispatcher ref is missing, or when the node count does not match.
|
|
46
|
+
*/
|
|
47
|
+
declare function resolveHookNames(fiber: Fiber, ref: DispatcherRef | null | undefined): Map<number, string[]>;
|
|
48
|
+
|
|
116
49
|
type HookOptions = Pick<Options, 'notifier' | 'silent' | 'console' | 'collapse' | 'logAll'>;
|
|
117
50
|
/**
|
|
118
51
|
* Track one component from the inside, without patching React:
|
|
@@ -147,67 +80,48 @@ declare function diffRecords(prev: Record<string, unknown> | undefined | null, n
|
|
|
147
80
|
|
|
148
81
|
interface BuildInput {
|
|
149
82
|
component: string;
|
|
83
|
+
instanceId?: number;
|
|
150
84
|
renderCount: number;
|
|
151
85
|
prevProps: Record<string, unknown>;
|
|
152
86
|
nextProps: Record<string, unknown>;
|
|
153
87
|
propChanges: Change[];
|
|
154
88
|
stateChanges?: Change[];
|
|
155
89
|
hookChanges?: HookChange[];
|
|
90
|
+
hookState?: HookSnapshot[];
|
|
91
|
+
contexts?: {
|
|
92
|
+
name: string;
|
|
93
|
+
value: unknown;
|
|
94
|
+
}[];
|
|
95
|
+
state?: Record<string, unknown>;
|
|
96
|
+
parent?: ParentInfo | null;
|
|
97
|
+
owner?: string | null;
|
|
98
|
+
path?: string[];
|
|
99
|
+
/** Default true: `useWhyRerender` and the console output assume the component decides on props alone. */
|
|
100
|
+
memoized?: boolean;
|
|
101
|
+
selfDuration?: number;
|
|
102
|
+
treeDuration?: number;
|
|
103
|
+
commitId?: number;
|
|
104
|
+
commitPriority?: CommitPriority;
|
|
105
|
+
source?: SourceLocation;
|
|
106
|
+
updaters?: string[];
|
|
107
|
+
commitCause?: CommitCause;
|
|
108
|
+
afterCommit?: number;
|
|
109
|
+
key?: string | null;
|
|
156
110
|
}
|
|
111
|
+
/** `useCart › useState#0` when custom hook names are known, else `useState #0`. */
|
|
112
|
+
declare const hookLabel: (c: {
|
|
113
|
+
hook: string;
|
|
114
|
+
index: number;
|
|
115
|
+
custom?: string[];
|
|
116
|
+
}) => string;
|
|
117
|
+
/** Store-specific advice for a `useSyncExternalStore` snapshot that is a new reference with equal contents. */
|
|
118
|
+
declare function storeAdvice(custom: string[] | undefined): string;
|
|
157
119
|
declare function buildReport(input: BuildInput): RenderReport;
|
|
158
120
|
declare function summarize(report: RenderReport): string;
|
|
159
121
|
/** Default notifier: prints a console group per report. */
|
|
160
122
|
declare function printReport(report: RenderReport, options: Options): void;
|
|
161
123
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
readonly reports: RenderReport[];
|
|
165
|
-
/** Reports where `avoidable` is true. */
|
|
166
|
-
readonly avoidable: RenderReport[];
|
|
167
|
-
/** Pass this to `init({ notifier })`. */
|
|
168
|
-
readonly notifier: Notifier;
|
|
169
|
-
clear(): void;
|
|
170
|
-
/** Throws with a readable message if any avoidable re-render was recorded. */
|
|
171
|
-
assertNoAvoidable(): void;
|
|
172
|
-
}
|
|
173
|
-
/** Collect reports in memory. Meant for tests. */
|
|
174
|
-
declare function createCollector(): Collector;
|
|
175
|
-
declare function combineNotifiers(...notifiers: Array<Notifier | undefined | null | false>): Notifier;
|
|
176
|
-
|
|
177
|
-
declare const DEVTOOLS_MARKER: "__rerenderLens";
|
|
178
|
-
declare const PROTOCOL_VERSION = 1;
|
|
179
|
-
interface DevtoolsMessage {
|
|
180
|
-
[DEVTOOLS_MARKER]: true;
|
|
181
|
-
version: number;
|
|
182
|
-
type: 'report' | 'clear' | 'hello';
|
|
183
|
-
payload?: unknown;
|
|
184
|
-
}
|
|
185
|
-
interface DevtoolsNotifierOptions {
|
|
186
|
-
/** How many reports to keep for `replay()`. Default 300. */
|
|
187
|
-
bufferSize?: number;
|
|
188
|
-
/** Where to post. Default `window`. */
|
|
189
|
-
target?: Pick<Window, 'postMessage'>;
|
|
190
|
-
/** Max serialization depth. Default 6. */
|
|
191
|
-
maxDepth?: number;
|
|
192
|
-
}
|
|
193
|
-
interface DevtoolsBridge {
|
|
194
|
-
/** Re-post every buffered report (a panel that opened late calls this). */
|
|
195
|
-
replay(): void;
|
|
196
|
-
clear(): void;
|
|
197
|
-
readonly size: number;
|
|
198
|
-
readonly version: number;
|
|
199
|
-
}
|
|
200
|
-
declare global {
|
|
201
|
-
interface Window {
|
|
202
|
-
__RERENDER_LENS_DEVTOOLS__?: DevtoolsBridge;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
/** Convert a report into a structured-clone-safe value (functions, elements, cycles removed). */
|
|
206
|
-
declare function serialize(value: unknown, maxDepth?: number, seen?: WeakSet<object>, depth?: number): unknown;
|
|
207
|
-
/**
|
|
208
|
-
* A notifier that posts every report on `window` for a DevTools extension to pick up.
|
|
209
|
-
* Also installs `window.__RERENDER_LENS_DEVTOOLS__` with `replay()` / `clear()`.
|
|
210
|
-
*/
|
|
211
|
-
declare function createDevtoolsNotifier(options?: DevtoolsNotifierOptions): Notifier;
|
|
124
|
+
/** Library version, injected by the build; "dev" when running from source. */
|
|
125
|
+
declare const VERSION: string;
|
|
212
126
|
|
|
213
|
-
export {
|
|
127
|
+
export { Change, ChangeKind, CommitCause, CommitPriority, type DispatcherRef, HookChange, HookSnapshot, Options, ParentInfo, RenderReport, SourceLocation, VERSION, buildReport, classify, configure, customHooksFromStack, deepEqual, diffRecords, disable, getDisplayName, hookLabel, init, isEnabled, printReport, resolveHookNames, shouldTrack, storeAdvice, summarize, track, useWhyRerender };
|