@buoy-gg/highlight-updates 2.0.2
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/README.md +210 -0
- package/lib/commonjs/highlight-updates/HighlightUpdatesOverlay.js +1 -0
- package/lib/commonjs/highlight-updates/components/HighlightFilterView.js +1 -0
- package/lib/commonjs/highlight-updates/components/HighlightUpdatesModal.js +1 -0
- package/lib/commonjs/highlight-updates/components/IdentifierBadge.js +1 -0
- package/lib/commonjs/highlight-updates/components/IsolatedRenderList.js +1 -0
- package/lib/commonjs/highlight-updates/components/ModalHeaderContent.js +1 -0
- package/lib/commonjs/highlight-updates/components/RenderCauseBadge.js +1 -0
- package/lib/commonjs/highlight-updates/components/RenderDetailView.js +1 -0
- package/lib/commonjs/highlight-updates/components/RenderHistoryViewer.js +1 -0
- package/lib/commonjs/highlight-updates/components/RenderListItem.js +1 -0
- package/lib/commonjs/highlight-updates/components/StatsDisplay.js +1 -0
- package/lib/commonjs/highlight-updates/components/index.js +1 -0
- package/lib/commonjs/highlight-updates/utils/HighlightUpdatesController.js +1 -0
- package/lib/commonjs/highlight-updates/utils/PerformanceLogger.js +1 -0
- package/lib/commonjs/highlight-updates/utils/ProfilerInterceptor.js +1 -0
- package/lib/commonjs/highlight-updates/utils/RenderCauseDetector.js +1 -0
- package/lib/commonjs/highlight-updates/utils/RenderTracker.js +1 -0
- package/lib/commonjs/highlight-updates/utils/ViewTypeMapper.js +1 -0
- package/lib/commonjs/index.js +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/preset.js +1 -0
- package/lib/module/highlight-updates/HighlightUpdatesOverlay.js +1 -0
- package/lib/module/highlight-updates/components/HighlightFilterView.js +1 -0
- package/lib/module/highlight-updates/components/HighlightUpdatesModal.js +1 -0
- package/lib/module/highlight-updates/components/IdentifierBadge.js +1 -0
- package/lib/module/highlight-updates/components/IsolatedRenderList.js +1 -0
- package/lib/module/highlight-updates/components/ModalHeaderContent.js +1 -0
- package/lib/module/highlight-updates/components/RenderCauseBadge.js +1 -0
- package/lib/module/highlight-updates/components/RenderDetailView.js +1 -0
- package/lib/module/highlight-updates/components/RenderHistoryViewer.js +1 -0
- package/lib/module/highlight-updates/components/RenderListItem.js +1 -0
- package/lib/module/highlight-updates/components/StatsDisplay.js +1 -0
- package/lib/module/highlight-updates/components/index.js +1 -0
- package/lib/module/highlight-updates/utils/HighlightUpdatesController.js +1 -0
- package/lib/module/highlight-updates/utils/PerformanceLogger.js +1 -0
- package/lib/module/highlight-updates/utils/ProfilerInterceptor.js +1 -0
- package/lib/module/highlight-updates/utils/RenderCauseDetector.js +1 -0
- package/lib/module/highlight-updates/utils/RenderTracker.js +1 -0
- package/lib/module/highlight-updates/utils/ViewTypeMapper.js +1 -0
- package/lib/module/index.js +1 -0
- package/lib/module/preset.js +1 -0
- package/lib/typescript/highlight-updates/HighlightUpdatesOverlay.d.ts +18 -0
- package/lib/typescript/highlight-updates/components/HighlightFilterView.d.ts +27 -0
- package/lib/typescript/highlight-updates/components/HighlightUpdatesModal.d.ts +36 -0
- package/lib/typescript/highlight-updates/components/IdentifierBadge.d.ts +39 -0
- package/lib/typescript/highlight-updates/components/IsolatedRenderList.d.ts +32 -0
- package/lib/typescript/highlight-updates/components/ModalHeaderContent.d.ts +68 -0
- package/lib/typescript/highlight-updates/components/RenderCauseBadge.d.ts +43 -0
- package/lib/typescript/highlight-updates/components/RenderDetailView.d.ts +29 -0
- package/lib/typescript/highlight-updates/components/RenderHistoryViewer.d.ts +36 -0
- package/lib/typescript/highlight-updates/components/RenderListItem.d.ts +16 -0
- package/lib/typescript/highlight-updates/components/StatsDisplay.d.ts +18 -0
- package/lib/typescript/highlight-updates/components/index.d.ts +12 -0
- package/lib/typescript/highlight-updates/utils/HighlightUpdatesController.d.ts +132 -0
- package/lib/typescript/highlight-updates/utils/PerformanceLogger.d.ts +135 -0
- package/lib/typescript/highlight-updates/utils/ProfilerInterceptor.d.ts +91 -0
- package/lib/typescript/highlight-updates/utils/RenderCauseDetector.d.ts +68 -0
- package/lib/typescript/highlight-updates/utils/RenderTracker.d.ts +407 -0
- package/lib/typescript/highlight-updates/utils/ViewTypeMapper.d.ts +66 -0
- package/lib/typescript/index.d.ts +43 -0
- package/lib/typescript/preset.d.ts +187 -0
- package/package.json +73 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PerformanceLogger
|
|
3
|
+
*
|
|
4
|
+
* Dedicated performance measurement utility for the Highlight Updates feature.
|
|
5
|
+
* Tracks timing metrics across the render detection pipeline to identify bottlenecks
|
|
6
|
+
* and measure optimization improvements.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* PerformanceLogger.setEnabled(true); // Enable logging
|
|
10
|
+
* const batch = PerformanceLogger.startBatch(nodesReceived);
|
|
11
|
+
* batch.markFilteringComplete(nodesFiltered, nodesToProcess);
|
|
12
|
+
* batch.markMeasurementComplete(successCount, failCount);
|
|
13
|
+
* batch.markTrackingComplete();
|
|
14
|
+
* batch.markCallbackComplete();
|
|
15
|
+
* batch.finish(); // Logs the complete metrics
|
|
16
|
+
*/
|
|
17
|
+
export interface BatchMetrics {
|
|
18
|
+
batchId: string;
|
|
19
|
+
timestamp: number;
|
|
20
|
+
nodesReceived: number;
|
|
21
|
+
nodesFiltered: number;
|
|
22
|
+
nodesToProcess: number;
|
|
23
|
+
batchSize: number;
|
|
24
|
+
nodesInBatch: number;
|
|
25
|
+
filteringTime: number;
|
|
26
|
+
measurementTime: number;
|
|
27
|
+
trackingTime: number;
|
|
28
|
+
callbackTime: number;
|
|
29
|
+
totalTime: number;
|
|
30
|
+
measurementSuccessCount: number;
|
|
31
|
+
measurementFailCount: number;
|
|
32
|
+
overlayRenderTime?: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Call this when a traceUpdates event is received to track end-to-end latency
|
|
36
|
+
*/
|
|
37
|
+
export declare function markEventReceived(): number;
|
|
38
|
+
/**
|
|
39
|
+
* Call this from the overlay when highlights are actually rendered
|
|
40
|
+
*/
|
|
41
|
+
export declare function markOverlayRendered(highlightCount: number, renderTime?: number): void;
|
|
42
|
+
export interface BatchTimer {
|
|
43
|
+
markFilteringComplete: (nodesFiltered: number, nodesToProcess: number) => void;
|
|
44
|
+
markMeasurementStart: () => void;
|
|
45
|
+
markMeasurementComplete: (successCount: number, failCount: number) => void;
|
|
46
|
+
markTrackingComplete: () => void;
|
|
47
|
+
markCallbackComplete: () => void;
|
|
48
|
+
setOverlayRenderTime: (timeMs: number) => void;
|
|
49
|
+
finish: () => BatchMetrics;
|
|
50
|
+
getBatchId: () => string;
|
|
51
|
+
}
|
|
52
|
+
type MetricsListener = (metrics: BatchMetrics) => void;
|
|
53
|
+
interface RollingStats {
|
|
54
|
+
batchCount: number;
|
|
55
|
+
totalNodes: number;
|
|
56
|
+
totalFiltered: number;
|
|
57
|
+
totalProcessed: number;
|
|
58
|
+
totalTime: number;
|
|
59
|
+
maxTime: number;
|
|
60
|
+
minTime: number;
|
|
61
|
+
avgMeasurementTime: number;
|
|
62
|
+
}
|
|
63
|
+
declare class PerformanceLoggerSingleton {
|
|
64
|
+
private enabled;
|
|
65
|
+
private batchCounter;
|
|
66
|
+
private listeners;
|
|
67
|
+
private rollingStats;
|
|
68
|
+
private recentBatches;
|
|
69
|
+
private readonly MAX_HISTORY;
|
|
70
|
+
private summaryInterval;
|
|
71
|
+
private readonly SUMMARY_INTERVAL_MS;
|
|
72
|
+
/**
|
|
73
|
+
* Enable or disable performance logging
|
|
74
|
+
*/
|
|
75
|
+
setEnabled(enabled: boolean): void;
|
|
76
|
+
/**
|
|
77
|
+
* Check if logging is enabled
|
|
78
|
+
*/
|
|
79
|
+
isEnabled(): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Start timing a new batch of render updates
|
|
82
|
+
*/
|
|
83
|
+
startBatch(nodesReceived: number, batchSize: number): BatchTimer;
|
|
84
|
+
/**
|
|
85
|
+
* Record metrics and log them
|
|
86
|
+
*/
|
|
87
|
+
private recordMetrics;
|
|
88
|
+
/**
|
|
89
|
+
* Log a single batch's metrics
|
|
90
|
+
*/
|
|
91
|
+
private logBatch;
|
|
92
|
+
/**
|
|
93
|
+
* Log periodic summary stats
|
|
94
|
+
*/
|
|
95
|
+
private logSummary;
|
|
96
|
+
/**
|
|
97
|
+
* Reset rolling statistics
|
|
98
|
+
*/
|
|
99
|
+
private resetStats;
|
|
100
|
+
/**
|
|
101
|
+
* Start the summary logging interval
|
|
102
|
+
*/
|
|
103
|
+
private startSummaryInterval;
|
|
104
|
+
/**
|
|
105
|
+
* Stop the summary logging interval
|
|
106
|
+
*/
|
|
107
|
+
private stopSummaryInterval;
|
|
108
|
+
/**
|
|
109
|
+
* Subscribe to metrics updates
|
|
110
|
+
*/
|
|
111
|
+
subscribe(listener: MetricsListener): () => void;
|
|
112
|
+
/**
|
|
113
|
+
* Notify all listeners of new metrics
|
|
114
|
+
*/
|
|
115
|
+
private notifyListeners;
|
|
116
|
+
/**
|
|
117
|
+
* Get recent batch history
|
|
118
|
+
*/
|
|
119
|
+
getRecentBatches(): BatchMetrics[];
|
|
120
|
+
/**
|
|
121
|
+
* Get current rolling stats
|
|
122
|
+
*/
|
|
123
|
+
getRollingStats(): RollingStats;
|
|
124
|
+
/**
|
|
125
|
+
* Clear all history and stats
|
|
126
|
+
*/
|
|
127
|
+
clear(): void;
|
|
128
|
+
/**
|
|
129
|
+
* Generate a detailed report of recent performance
|
|
130
|
+
*/
|
|
131
|
+
generateReport(): string;
|
|
132
|
+
}
|
|
133
|
+
export declare const PerformanceLogger: PerformanceLoggerSingleton;
|
|
134
|
+
export default PerformanceLogger;
|
|
135
|
+
//# sourceMappingURL=PerformanceLogger.d.ts.map
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProfilerInterceptor
|
|
3
|
+
*
|
|
4
|
+
* Swizzles React DevTools internals to capture and log exactly what the
|
|
5
|
+
* profiler detects when "Highlight updates when components render" is enabled.
|
|
6
|
+
*
|
|
7
|
+
* This allows us to compare profiler detection with our own implementation
|
|
8
|
+
* to ensure 100% accuracy.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* import { installProfilerInterceptor } from './ProfilerInterceptor';
|
|
12
|
+
* installProfilerInterceptor();
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Log information about available renderer interfaces.
|
|
16
|
+
* Only call this manually for debugging - not called during normal operation.
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
export declare function logRendererInterfaces(): void;
|
|
20
|
+
/**
|
|
21
|
+
* Log hook structure for debugging.
|
|
22
|
+
* Only call this manually for debugging - not called during normal operation.
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
export declare function logHookStructure(): void;
|
|
26
|
+
/**
|
|
27
|
+
* Enable trace updates on all renderer interfaces
|
|
28
|
+
*
|
|
29
|
+
* This is what DevTools does when you check "Highlight updates when components render"
|
|
30
|
+
*
|
|
31
|
+
* Reference: backend.js line 15487-15489
|
|
32
|
+
* function setTraceUpdatesEnabled(isEnabled) {
|
|
33
|
+
* traceUpdatesEnabled = isEnabled;
|
|
34
|
+
* }
|
|
35
|
+
*/
|
|
36
|
+
declare function enableTracingOnAllRenderers(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Disable trace updates on all renderer interfaces
|
|
39
|
+
*/
|
|
40
|
+
declare function disableTracingOnAllRenderers(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Set a callback to receive profiler nodes for comparison
|
|
43
|
+
*/
|
|
44
|
+
export declare function setComparisonCallback(callback: ((nodes: Set<unknown>) => void) | null): void;
|
|
45
|
+
/**
|
|
46
|
+
* Install all profiler interception hooks
|
|
47
|
+
*
|
|
48
|
+
* Call this early in your app initialization to capture all events.
|
|
49
|
+
* Installation is silent - no console logs in normal operation.
|
|
50
|
+
*/
|
|
51
|
+
export declare function installProfilerInterceptor(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Uninstall profiler interception hooks and restore original functions
|
|
54
|
+
*/
|
|
55
|
+
export declare function uninstallProfilerInterceptor(): void;
|
|
56
|
+
/**
|
|
57
|
+
* Check if interceptor is currently installed
|
|
58
|
+
*/
|
|
59
|
+
export declare function isInterceptorInstalled(): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Enable profiler logging - starts logging all profiler events
|
|
62
|
+
*
|
|
63
|
+
* NOTE: This only enables LOGGING of events. It does NOT enable tracing.
|
|
64
|
+
* The profiler must be enabled separately (e.g., via Chrome DevTools checkbox)
|
|
65
|
+
* for events to be emitted. This allows us to compare what the real profiler
|
|
66
|
+
* detects without our code interfering.
|
|
67
|
+
*/
|
|
68
|
+
export declare function enableProfilerLogging(): void;
|
|
69
|
+
/**
|
|
70
|
+
* Disable profiler logging - stops logging profiler events
|
|
71
|
+
* NOTE: Does NOT disable tracing - the profiler continues to work,
|
|
72
|
+
* we just stop logging its events
|
|
73
|
+
*/
|
|
74
|
+
export declare function disableProfilerLogging(): void;
|
|
75
|
+
/**
|
|
76
|
+
* Check if logging is currently enabled
|
|
77
|
+
*/
|
|
78
|
+
export declare function isLoggingEnabled(): boolean;
|
|
79
|
+
declare const _default: {
|
|
80
|
+
install: typeof installProfilerInterceptor;
|
|
81
|
+
uninstall: typeof uninstallProfilerInterceptor;
|
|
82
|
+
isInstalled: typeof isInterceptorInstalled;
|
|
83
|
+
setComparisonCallback: typeof setComparisonCallback;
|
|
84
|
+
enableTracing: typeof enableTracingOnAllRenderers;
|
|
85
|
+
disableTracing: typeof disableTracingOnAllRenderers;
|
|
86
|
+
enableLogging: typeof enableProfilerLogging;
|
|
87
|
+
disableLogging: typeof disableProfilerLogging;
|
|
88
|
+
isLoggingEnabled: typeof isLoggingEnabled;
|
|
89
|
+
};
|
|
90
|
+
export default _default;
|
|
91
|
+
//# sourceMappingURL=ProfilerInterceptor.d.ts.map
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RenderCauseDetector
|
|
3
|
+
*
|
|
4
|
+
* Detects WHY a component rendered by comparing current fiber state
|
|
5
|
+
* to previously stored state. Supports detection of:
|
|
6
|
+
* - First mount
|
|
7
|
+
* - Props changes (with changed key names)
|
|
8
|
+
* - Hooks/state changes (with hook indices)
|
|
9
|
+
* - Parent re-renders
|
|
10
|
+
*
|
|
11
|
+
* TWO-LEVEL CAUSATION:
|
|
12
|
+
* 1. Native level: Why did the native view's props change? (style, accessibilityState, etc.)
|
|
13
|
+
* 2. Component level: Why did the owning React component re-render? (props, state, parent)
|
|
14
|
+
*
|
|
15
|
+
* This gives the full picture:
|
|
16
|
+
* "StepperValueDisplay re-rendered because PARENT, which caused native Text to update PROPS [style]"
|
|
17
|
+
*
|
|
18
|
+
* COMPONENT-SPECIFIC DETECTION:
|
|
19
|
+
* Different native components have different important props:
|
|
20
|
+
* - RCTText: `children` IS the text content - always track it
|
|
21
|
+
* - RCTView: `children` is React elements - skip it
|
|
22
|
+
* - RCTImageView: `source` is the image URL - track it
|
|
23
|
+
*
|
|
24
|
+
* See: RENDER_CAUSE_TEXT_COMPONENT_PLAN.md for full documentation
|
|
25
|
+
*/
|
|
26
|
+
import type { RenderCause, DebugLogLevel } from "./RenderTracker";
|
|
27
|
+
/**
|
|
28
|
+
* Detect why a component rendered
|
|
29
|
+
*
|
|
30
|
+
* @param nativeTag - The native tag of the component
|
|
31
|
+
* @param fiber - The React fiber object (host fiber)
|
|
32
|
+
* @param batchNativeTags - Set of all nativeTags in this render batch (for parent detection)
|
|
33
|
+
* @param debugLogLevel - Debug logging level: "off" | "minimal" | "verbose" | "all"
|
|
34
|
+
* @returns RenderCause object describing why the component rendered
|
|
35
|
+
*/
|
|
36
|
+
export declare function detectRenderCause(nativeTag: number, fiber: any, batchNativeTags: Set<number>, debugLogLevel?: DebugLogLevel): RenderCause;
|
|
37
|
+
/**
|
|
38
|
+
* Clear all stored states
|
|
39
|
+
* Call this when tracking is disabled to prevent memory leaks
|
|
40
|
+
*/
|
|
41
|
+
export declare function clearRenderCauseState(): void;
|
|
42
|
+
/**
|
|
43
|
+
* Remove a specific component from state storage
|
|
44
|
+
* Useful when a component is unmounted
|
|
45
|
+
*/
|
|
46
|
+
export declare function removeRenderCauseState(nativeTag: number): void;
|
|
47
|
+
/**
|
|
48
|
+
* Get storage stats for debugging/display
|
|
49
|
+
*/
|
|
50
|
+
export declare function getRenderCauseStats(): {
|
|
51
|
+
storedStates: number;
|
|
52
|
+
maxStates: number;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Safely clone props/state for history storage.
|
|
56
|
+
* Handles circular references, functions, and large objects.
|
|
57
|
+
*/
|
|
58
|
+
export declare function safeCloneForHistory(value: any, depth?: number, seen?: WeakSet<object>): any;
|
|
59
|
+
/**
|
|
60
|
+
* Capture props snapshot from a fiber for history storage
|
|
61
|
+
*/
|
|
62
|
+
export declare function capturePropsSnapshot(fiber: any): Record<string, any> | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* Capture state snapshot from a fiber for history storage
|
|
65
|
+
* For function components, this walks the hooks linked list
|
|
66
|
+
*/
|
|
67
|
+
export declare function captureStateSnapshot(fiber: any): any;
|
|
68
|
+
//# sourceMappingURL=RenderCauseDetector.d.ts.map
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RenderTracker
|
|
3
|
+
*
|
|
4
|
+
* Singleton that tracks component render history for the Highlight Updates modal.
|
|
5
|
+
* Stores information about each tracked component including render counts,
|
|
6
|
+
* timestamps, and identifying props (testID, nativeID, etc.)
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Debug logging levels for render cause detection.
|
|
10
|
+
* Controls verbosity of console output for debugging "Why Did You Render" feature.
|
|
11
|
+
*
|
|
12
|
+
* - "off": No debug logging (default, best for production)
|
|
13
|
+
* - "minimal": Only log state/hook value changes (e.g., "useState: 3334 → 3335")
|
|
14
|
+
* - "verbose": Log component info + cause + value changes
|
|
15
|
+
* - "all": Full fiber dump with everything (native fiber, component fiber, hooks, batch context)
|
|
16
|
+
*/
|
|
17
|
+
export type DebugLogLevel = "off" | "minimal" | "verbose" | "all";
|
|
18
|
+
export type RenderCauseType = "mount" | "props" | "state" | "hooks" | "context" | "parent" | "unknown";
|
|
19
|
+
export type ComponentCauseType = "mount" | "props" | "state" | "parent" | "unknown";
|
|
20
|
+
/**
|
|
21
|
+
* Represents a change in a single hook's state
|
|
22
|
+
* Used to show meaningful before/after values for debugging
|
|
23
|
+
*/
|
|
24
|
+
export interface HookStateChange {
|
|
25
|
+
/** Hook index in the linked list (0-based) */
|
|
26
|
+
index: number;
|
|
27
|
+
/** Detected hook type */
|
|
28
|
+
type: 'useState' | 'useReducer' | 'useRef' | 'useMemo' | 'useCallback' | 'useEffect' | 'unknown';
|
|
29
|
+
/** Previous value (if available) */
|
|
30
|
+
previousValue?: any;
|
|
31
|
+
/** Current value */
|
|
32
|
+
currentValue?: any;
|
|
33
|
+
/** Human-readable description of the change */
|
|
34
|
+
description?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface RenderCause {
|
|
37
|
+
type: RenderCauseType;
|
|
38
|
+
changedKeys?: string[];
|
|
39
|
+
hookIndices?: number[];
|
|
40
|
+
/** Detailed hook state changes with actual values (Phase 3 enhancement) */
|
|
41
|
+
hookChanges?: HookStateChange[];
|
|
42
|
+
timestamp: number;
|
|
43
|
+
componentCause?: ComponentCauseType;
|
|
44
|
+
componentName?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* A single render event in the history
|
|
48
|
+
* Captures everything about one render occurrence
|
|
49
|
+
*/
|
|
50
|
+
export interface RenderEvent {
|
|
51
|
+
id: string;
|
|
52
|
+
timestamp: number;
|
|
53
|
+
cause: RenderCause;
|
|
54
|
+
capturedProps?: Record<string, any>;
|
|
55
|
+
capturedState?: any;
|
|
56
|
+
renderNumber: number;
|
|
57
|
+
}
|
|
58
|
+
export interface TrackedRender {
|
|
59
|
+
id: string;
|
|
60
|
+
nativeTag: number;
|
|
61
|
+
viewType: string;
|
|
62
|
+
displayName: string;
|
|
63
|
+
testID?: string;
|
|
64
|
+
nativeID?: string;
|
|
65
|
+
accessibilityLabel?: string;
|
|
66
|
+
componentName?: string;
|
|
67
|
+
renderCount: number;
|
|
68
|
+
firstRenderTime: number;
|
|
69
|
+
lastRenderTime: number;
|
|
70
|
+
measurements?: {
|
|
71
|
+
x: number;
|
|
72
|
+
y: number;
|
|
73
|
+
width: number;
|
|
74
|
+
height: number;
|
|
75
|
+
};
|
|
76
|
+
color: string;
|
|
77
|
+
lastRenderCause?: RenderCause;
|
|
78
|
+
renderHistory?: RenderEvent[];
|
|
79
|
+
}
|
|
80
|
+
export type FilterType = "any" | "viewType" | "testID" | "nativeID" | "component" | "accessibilityLabel";
|
|
81
|
+
export interface FilterPattern {
|
|
82
|
+
type: FilterType;
|
|
83
|
+
value: string;
|
|
84
|
+
}
|
|
85
|
+
export interface FilterConfig {
|
|
86
|
+
includeTestID: Set<string>;
|
|
87
|
+
includeNativeID: Set<string>;
|
|
88
|
+
includeViewType: Set<string>;
|
|
89
|
+
includeComponent: Set<string>;
|
|
90
|
+
excludeTestID: Set<string>;
|
|
91
|
+
excludeNativeID: Set<string>;
|
|
92
|
+
excludeViewType: Set<string>;
|
|
93
|
+
excludeComponent: Set<string>;
|
|
94
|
+
includePatterns: FilterPattern[];
|
|
95
|
+
excludePatterns: FilterPattern[];
|
|
96
|
+
minRenderCount?: number;
|
|
97
|
+
maxRenderCount?: number;
|
|
98
|
+
}
|
|
99
|
+
type RenderTrackerListener = (renders: TrackedRender[]) => void;
|
|
100
|
+
type StateListener = (state: {
|
|
101
|
+
isTracking: boolean;
|
|
102
|
+
isPaused: boolean;
|
|
103
|
+
}) => void;
|
|
104
|
+
type SettingsListener = (settings: RenderTrackerSettings) => void;
|
|
105
|
+
type FilterListener = (filters: FilterConfig) => void;
|
|
106
|
+
export interface RenderTrackerSettings {
|
|
107
|
+
/**
|
|
108
|
+
* Maximum number of components to highlight per batch.
|
|
109
|
+
* Higher values show more highlights but may impact performance.
|
|
110
|
+
* Range: 10-500, Default: 150
|
|
111
|
+
*/
|
|
112
|
+
batchSize: number;
|
|
113
|
+
/**
|
|
114
|
+
* Whether to show and track render counts on highlight badges.
|
|
115
|
+
* Disabling this improves performance by skipping count tracking.
|
|
116
|
+
* Default: true
|
|
117
|
+
*/
|
|
118
|
+
showRenderCount: boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Whether to enable performance logging to the console.
|
|
121
|
+
* Logs detailed timing metrics for each batch of highlights.
|
|
122
|
+
* Useful for debugging and optimization.
|
|
123
|
+
* Default: false
|
|
124
|
+
*/
|
|
125
|
+
performanceLogging: boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Whether to track and display render causes (why components rendered).
|
|
128
|
+
* Detects props changes, hooks changes, parent re-renders, and first mounts.
|
|
129
|
+
* Adds ~2-5% performance overhead and stores previous component state in memory.
|
|
130
|
+
* Requires showRenderCount to be enabled.
|
|
131
|
+
* Default: false
|
|
132
|
+
*/
|
|
133
|
+
trackRenderCauses: boolean;
|
|
134
|
+
/**
|
|
135
|
+
* Whether to enable render history tracking.
|
|
136
|
+
* When enabled, stores a history of render events per component for
|
|
137
|
+
* event stepping and diff visualization. Has memory and performance overhead.
|
|
138
|
+
* Requires trackRenderCauses to be enabled.
|
|
139
|
+
* Default: false
|
|
140
|
+
*/
|
|
141
|
+
enableRenderHistory: boolean;
|
|
142
|
+
/**
|
|
143
|
+
* Maximum number of render events to store per component.
|
|
144
|
+
* Older events are discarded when this limit is reached.
|
|
145
|
+
* Range: 5-50, Default: 20
|
|
146
|
+
*/
|
|
147
|
+
maxRenderHistoryPerComponent: number;
|
|
148
|
+
/**
|
|
149
|
+
* Whether to capture props at each render for diff visualization.
|
|
150
|
+
* Enabling this allows comparing props between renders but increases
|
|
151
|
+
* memory usage significantly. Only effective when enableRenderHistory is true.
|
|
152
|
+
* Default: false
|
|
153
|
+
*/
|
|
154
|
+
capturePropsOnRender: boolean;
|
|
155
|
+
/**
|
|
156
|
+
* Whether to capture state at each render for diff visualization.
|
|
157
|
+
* Enabling this allows comparing state between renders but increases
|
|
158
|
+
* memory usage. Only effective when enableRenderHistory is true.
|
|
159
|
+
* Default: false
|
|
160
|
+
*/
|
|
161
|
+
captureStateOnRender: boolean;
|
|
162
|
+
/**
|
|
163
|
+
* Debug logging level for render cause detection.
|
|
164
|
+
* Controls console output verbosity for "Why Did You Render" debugging.
|
|
165
|
+
*
|
|
166
|
+
* - "off": No debug logging (default)
|
|
167
|
+
* - "minimal": Only state/hook value changes (e.g., "useState: 3334 → 3335")
|
|
168
|
+
* - "verbose": Component info + cause + value changes
|
|
169
|
+
* - "all": Full fiber dump with everything
|
|
170
|
+
*
|
|
171
|
+
* Default: "off"
|
|
172
|
+
*/
|
|
173
|
+
debugLogLevel: DebugLogLevel;
|
|
174
|
+
/**
|
|
175
|
+
* @deprecated Use debugLogLevel instead. Kept for backward compatibility.
|
|
176
|
+
* When true, equivalent to debugLogLevel: "all"
|
|
177
|
+
*/
|
|
178
|
+
debugRawFiberLogging: boolean;
|
|
179
|
+
}
|
|
180
|
+
declare class RenderTrackerSingleton {
|
|
181
|
+
private renders;
|
|
182
|
+
private listeners;
|
|
183
|
+
private stateListeners;
|
|
184
|
+
private settingsListeners;
|
|
185
|
+
private filterListeners;
|
|
186
|
+
private isTracking;
|
|
187
|
+
private isPaused;
|
|
188
|
+
private settings;
|
|
189
|
+
private isBatchMode;
|
|
190
|
+
private batchDirty;
|
|
191
|
+
private filters;
|
|
192
|
+
/**
|
|
193
|
+
* Track a component render
|
|
194
|
+
*/
|
|
195
|
+
trackRender(data: {
|
|
196
|
+
nativeTag: number;
|
|
197
|
+
viewType: string;
|
|
198
|
+
testID?: string;
|
|
199
|
+
nativeID?: string;
|
|
200
|
+
accessibilityLabel?: string;
|
|
201
|
+
componentName?: string;
|
|
202
|
+
measurements?: {
|
|
203
|
+
x: number;
|
|
204
|
+
y: number;
|
|
205
|
+
width: number;
|
|
206
|
+
height: number;
|
|
207
|
+
};
|
|
208
|
+
color: string;
|
|
209
|
+
count: number;
|
|
210
|
+
renderCause?: RenderCause;
|
|
211
|
+
capturedProps?: Record<string, any>;
|
|
212
|
+
capturedState?: any;
|
|
213
|
+
}): void;
|
|
214
|
+
/**
|
|
215
|
+
* Add a render event to a component's history (circular buffer)
|
|
216
|
+
*/
|
|
217
|
+
private addRenderEvent;
|
|
218
|
+
/**
|
|
219
|
+
* Start batch mode - defers listener notifications until endBatch() is called.
|
|
220
|
+
* Use this when tracking multiple renders in a loop to avoid O(n²) notifications.
|
|
221
|
+
*/
|
|
222
|
+
startBatch(): void;
|
|
223
|
+
/**
|
|
224
|
+
* End batch mode and notify listeners if any renders were tracked.
|
|
225
|
+
*/
|
|
226
|
+
endBatch(): void;
|
|
227
|
+
/**
|
|
228
|
+
* Get all tracked renders
|
|
229
|
+
* Creates new object copies to trigger React.memo re-renders
|
|
230
|
+
*/
|
|
231
|
+
getRenders(): TrackedRender[];
|
|
232
|
+
/**
|
|
233
|
+
* Check if a component passes all active filters.
|
|
234
|
+
* Used by both the modal list and the overlay to filter components.
|
|
235
|
+
*
|
|
236
|
+
* @param info Component info to check (can be TrackedRender or extracted component info)
|
|
237
|
+
* @returns true if the component passes all filters, false if it should be hidden
|
|
238
|
+
*/
|
|
239
|
+
passesFilters(info: {
|
|
240
|
+
viewType: string;
|
|
241
|
+
displayName?: string;
|
|
242
|
+
testID?: string;
|
|
243
|
+
nativeID?: string;
|
|
244
|
+
accessibilityLabel?: string;
|
|
245
|
+
componentName?: string;
|
|
246
|
+
}): boolean;
|
|
247
|
+
/**
|
|
248
|
+
* Check if component info matches any of the given patterns
|
|
249
|
+
*/
|
|
250
|
+
private matchesAnyPatternForInfo;
|
|
251
|
+
/**
|
|
252
|
+
* Check if any filters are currently active
|
|
253
|
+
*/
|
|
254
|
+
hasActiveFilters(): boolean;
|
|
255
|
+
/**
|
|
256
|
+
* Get filtered renders based on current filter config
|
|
257
|
+
*/
|
|
258
|
+
getFilteredRenders(searchText?: string): TrackedRender[];
|
|
259
|
+
/**
|
|
260
|
+
* Check if a value matches any pattern in the set
|
|
261
|
+
*/
|
|
262
|
+
private matchesPattern;
|
|
263
|
+
/**
|
|
264
|
+
* Get a single render by id
|
|
265
|
+
*/
|
|
266
|
+
getRender(id: string): TrackedRender | undefined;
|
|
267
|
+
/**
|
|
268
|
+
* Clear all tracked renders
|
|
269
|
+
*/
|
|
270
|
+
clear(): void;
|
|
271
|
+
/**
|
|
272
|
+
* Reset render count for a specific component
|
|
273
|
+
*/
|
|
274
|
+
resetRenderCount(id: string): void;
|
|
275
|
+
/**
|
|
276
|
+
* Start tracking
|
|
277
|
+
*/
|
|
278
|
+
start(): void;
|
|
279
|
+
/**
|
|
280
|
+
* Stop tracking
|
|
281
|
+
*/
|
|
282
|
+
stop(): void;
|
|
283
|
+
/**
|
|
284
|
+
* Pause tracking (keeps state but stops adding new renders)
|
|
285
|
+
*/
|
|
286
|
+
pause(): void;
|
|
287
|
+
/**
|
|
288
|
+
* Resume tracking
|
|
289
|
+
*/
|
|
290
|
+
resume(): void;
|
|
291
|
+
/**
|
|
292
|
+
* Toggle pause state
|
|
293
|
+
*/
|
|
294
|
+
togglePause(): void;
|
|
295
|
+
/**
|
|
296
|
+
* Get current tracking state
|
|
297
|
+
*/
|
|
298
|
+
getState(): {
|
|
299
|
+
isTracking: boolean;
|
|
300
|
+
isPaused: boolean;
|
|
301
|
+
};
|
|
302
|
+
/**
|
|
303
|
+
* Get filter config
|
|
304
|
+
*/
|
|
305
|
+
getFilters(): FilterConfig;
|
|
306
|
+
/**
|
|
307
|
+
* Update filter config
|
|
308
|
+
*/
|
|
309
|
+
setFilters(filters: Partial<FilterConfig>): void;
|
|
310
|
+
/**
|
|
311
|
+
* Add an include pattern
|
|
312
|
+
*/
|
|
313
|
+
addIncludePattern(type: "testID" | "nativeID" | "viewType" | "component", pattern: string): void;
|
|
314
|
+
/**
|
|
315
|
+
* Remove an include pattern
|
|
316
|
+
*/
|
|
317
|
+
removeIncludePattern(type: "testID" | "nativeID" | "viewType" | "component", pattern: string): void;
|
|
318
|
+
/**
|
|
319
|
+
* Add an exclude pattern
|
|
320
|
+
*/
|
|
321
|
+
addExcludePattern(type: "testID" | "nativeID" | "viewType" | "component", pattern: string): void;
|
|
322
|
+
/**
|
|
323
|
+
* Remove an exclude pattern
|
|
324
|
+
*/
|
|
325
|
+
removeExcludePattern(type: "testID" | "nativeID" | "viewType" | "component", pattern: string): void;
|
|
326
|
+
/**
|
|
327
|
+
* Clear all filters
|
|
328
|
+
*/
|
|
329
|
+
clearFilters(): void;
|
|
330
|
+
/**
|
|
331
|
+
* Get available prop values from tracked renders
|
|
332
|
+
*/
|
|
333
|
+
getAvailableProps(): {
|
|
334
|
+
viewTypes: string[];
|
|
335
|
+
testIDs: string[];
|
|
336
|
+
nativeIDs: string[];
|
|
337
|
+
componentNames: string[];
|
|
338
|
+
accessibilityLabels: string[];
|
|
339
|
+
};
|
|
340
|
+
/**
|
|
341
|
+
* Get summary stats
|
|
342
|
+
*/
|
|
343
|
+
getStats(): {
|
|
344
|
+
totalComponents: number;
|
|
345
|
+
totalRenders: number;
|
|
346
|
+
};
|
|
347
|
+
/**
|
|
348
|
+
* Subscribe to render updates
|
|
349
|
+
*/
|
|
350
|
+
subscribe(listener: RenderTrackerListener): () => void;
|
|
351
|
+
/**
|
|
352
|
+
* Subscribe to state changes (tracking/paused)
|
|
353
|
+
*/
|
|
354
|
+
subscribeToState(listener: StateListener): () => void;
|
|
355
|
+
/**
|
|
356
|
+
* Subscribe to settings changes
|
|
357
|
+
*/
|
|
358
|
+
subscribeToSettings(listener: SettingsListener): () => void;
|
|
359
|
+
/**
|
|
360
|
+
* Subscribe to filter changes
|
|
361
|
+
*/
|
|
362
|
+
subscribeToFilters(listener: FilterListener): () => void;
|
|
363
|
+
/**
|
|
364
|
+
* Check if a render should be visible based on current filters
|
|
365
|
+
* Used by the overlay to filter frozen highlights
|
|
366
|
+
*/
|
|
367
|
+
shouldShowRender(render: TrackedRender): boolean;
|
|
368
|
+
/**
|
|
369
|
+
* Get current settings
|
|
370
|
+
*/
|
|
371
|
+
getSettings(): RenderTrackerSettings;
|
|
372
|
+
/**
|
|
373
|
+
* Update settings
|
|
374
|
+
*/
|
|
375
|
+
setSettings(newSettings: Partial<RenderTrackerSettings>): void;
|
|
376
|
+
/**
|
|
377
|
+
* Clear render history for all components
|
|
378
|
+
*/
|
|
379
|
+
clearAllRenderHistory(): void;
|
|
380
|
+
/**
|
|
381
|
+
* Clear render history for a specific component
|
|
382
|
+
*/
|
|
383
|
+
clearRenderHistory(id: string): void;
|
|
384
|
+
/**
|
|
385
|
+
* Get render history stats for debugging
|
|
386
|
+
*/
|
|
387
|
+
getRenderHistoryStats(): {
|
|
388
|
+
totalEvents: number;
|
|
389
|
+
componentsWithHistory: number;
|
|
390
|
+
averageEventsPerComponent: number;
|
|
391
|
+
};
|
|
392
|
+
/**
|
|
393
|
+
* Get batch size (convenience method)
|
|
394
|
+
*/
|
|
395
|
+
getBatchSize(): number;
|
|
396
|
+
/**
|
|
397
|
+
* Set batch size (convenience method)
|
|
398
|
+
*/
|
|
399
|
+
setBatchSize(size: number): void;
|
|
400
|
+
private notifyListeners;
|
|
401
|
+
private notifyStateListeners;
|
|
402
|
+
private notifySettingsListeners;
|
|
403
|
+
private notifyFilterListeners;
|
|
404
|
+
}
|
|
405
|
+
export declare const RenderTracker: RenderTrackerSingleton;
|
|
406
|
+
export default RenderTracker;
|
|
407
|
+
//# sourceMappingURL=RenderTracker.d.ts.map
|