react-render-detective 0.4.0 → 0.6.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 +299 -0
- package/README.md +2 -2
- package/dist/babel.cjs +2 -2
- package/dist/babel.d.cts +11 -0
- package/dist/babel.d.ts +11 -0
- package/dist/babel.js +1 -1
- package/dist/{chunk-QOGTEVBP.js → chunk-3TZNM7JO.js} +103 -4
- package/dist/chunk-3TZNM7JO.js.map +1 -0
- package/dist/{chunk-HOTY7J3X.js → chunk-D7M4UC3Y.js} +26 -2
- package/dist/chunk-D7M4UC3Y.js.map +1 -0
- package/dist/{chunk-PHYYA67T.cjs → chunk-EXDRRUUQ.cjs} +69 -2
- package/dist/chunk-EXDRRUUQ.cjs.map +1 -0
- package/dist/{chunk-DZ3BZ654.cjs → chunk-LCGXVRJR.cjs} +103 -4
- package/dist/chunk-LCGXVRJR.cjs.map +1 -0
- package/dist/{chunk-MCIQMYNR.js → chunk-QVHAC7AD.js} +69 -2
- package/dist/chunk-QVHAC7AD.js.map +1 -0
- package/dist/{chunk-JD4IJ4MN.cjs → chunk-RGT44QQI.cjs} +26 -2
- package/dist/chunk-RGT44QQI.cjs.map +1 -0
- package/dist/core.cjs +18 -18
- package/dist/core.d.cts +27 -3
- package/dist/core.d.ts +27 -3
- package/dist/core.js +1 -1
- package/dist/index.cjs +197 -295
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -115
- package/dist/index.d.ts +35 -115
- package/dist/index.js +166 -258
- package/dist/index.js.map +1 -1
- package/dist/interactions.cjs +252 -0
- package/dist/interactions.cjs.map +1 -0
- package/dist/interactions.d.cts +110 -0
- package/dist/interactions.d.ts +110 -0
- package/dist/interactions.js +241 -0
- package/dist/interactions.js.map +1 -0
- package/dist/overlay.cjs +5 -5
- package/dist/overlay.js +2 -2
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/{types-gl13xwmN.d.cts → types-CRET8EhB.d.cts} +20 -2
- package/dist/{types-gl13xwmN.d.ts → types-CRET8EhB.d.ts} +20 -2
- package/dist/vite.cjs +2 -2
- package/dist/vite.js +1 -1
- package/package.json +14 -4
- package/dist/chunk-DZ3BZ654.cjs.map +0 -1
- package/dist/chunk-HOTY7J3X.js.map +0 -1
- package/dist/chunk-JD4IJ4MN.cjs.map +0 -1
- package/dist/chunk-MCIQMYNR.js.map +0 -1
- package/dist/chunk-PHYYA67T.cjs.map +0 -1
- package/dist/chunk-QOGTEVBP.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/babel/index.ts"],"names":[],"mappings":"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","file":"chunk-QVHAC7AD.js","sourcesContent":["/**\n * Babel plugin: instrument every React component in a file at build time.\n *\n * Why this exists: without it you only learn about components you already\n * suspected, because you have to wrap them by hand. With it, the tool reports\n * on the whole tree — and it can attach a real source location, which React\n * itself no longer exposes at runtime (`_debugSource` was removed in React 19).\n *\n * Build-time only. It must never run in a production build, and it removes\n * itself when `NODE_ENV` is production unless explicitly forced.\n */\nimport type { NodePath, PluginObject, PluginPass, types as BabelTypes } from \"@babel/core\";\n\nexport interface RenderDetectivePluginOptions {\n /** Defaults to `NODE_ENV !== \"production\"`. */\n enabled?: boolean;\n /** Only instrument files whose path matches. Empty = all files. */\n include?: Array<string | RegExp>;\n /** Skip files whose path matches. Applied after `include`. */\n exclude?: Array<string | RegExp>;\n /**\n * Skip files with no `\"use client\"` directive. Turn this on for the Next.js\n * app router: server components never render on the client, and wrapping one\n * in a hook-using HOC would break the build.\n */\n clientOnly?: boolean;\n /** Import specifier for the runtime. Overridable for testing and monorepos. */\n importSource?: string;\n /** Root used to make source locations relative. Defaults to `process.cwd()`. */\n root?: string;\n /**\n * Attribute external-store renders by wrapping store hooks at their call site.\n * Defaults to `true`. Without it, a Redux-driven render can only be reported\n * as \"state or an external store\".\n */\n trackStores?: boolean;\n /**\n * Which hooks to wrap, as `package` → hook names. Defaults to react-redux's\n * `useSelector`. Add your own store's hook here.\n */\n storeHooks?: Record<string, string[]>;\n}\n\ninterface State extends PluginPass {\n opts: RenderDetectivePluginOptions;\n rrdLocal?: BabelTypes.Identifier;\n rrdTrackSelectorLocal?: BabelTypes.Identifier;\n rrdTouched?: boolean;\n rrdRelativePath?: string;\n /** Local names bound to a tracked store hook in this file. */\n rrdStoreHooks?: Set<string>;\n}\n\nconst DEFAULT_IMPORT_SOURCE = \"react-render-detective\";\n\n/*\n * Never instrument the detective's own runtime. Its HOC returns a component\n * that renders the component it was given; instrumenting that makes it render\n * itself, and the app dies with a stack overflow before the first paint.\n *\n * node_modules covers the normal install. This covers a source alias — how the\n * bundled example consumes the package, and how anyone working on it locally\n * would too.\n */\nconst SELF_PATTERN = /[/\\\\]react-render-detective[/\\\\](src|dist)[/\\\\]/;\nconst HOC_NAMES = new Set([\"memo\", \"forwardRef\"]);\n\nconst DEFAULT_STORE_HOOKS: Record<string, string[]> = {\n \"react-redux\": [\"useSelector\"],\n};\n\nexport default function renderDetectiveBabelPlugin(\n api: { types: typeof BabelTypes; assertVersion?: (v: number | string) => void },\n): PluginObject {\n const t = api.types;\n /*\n * Guards against re-processing a node we just rewrote. Using `path.skip()`\n * for that was a mistake: it skips the entire subtree, so components declared\n * *inside* another component were never instrumented — exactly the case the\n * remount diagnosis exists to catch.\n */\n const processed = new WeakSet<BabelTypes.Node>();\n // Babel 7 and 8 both work: only `types`, `NodePath` and the visitor shape are\n // used, all stable across the major.\n api.assertVersion?.(\"^7.0.0-0 || ^8.0.0-0\");\n\n /**\n * A component is an uppercase-named function that returns JSX.\n *\n * No all-caps exclusion: it was rejecting `const A = () => <i />`, a perfectly\n * ordinary component, to guard against constants that in practice are values\n * rather than functions returning JSX — and the JSX check already covers that.\n */\n const isComponentName = (name: string | undefined | null): boolean => !!name && /^[A-Z]/.test(name);\n\n function returnsJsx(path: NodePath<BabelTypes.Function>): boolean {\n let found = false;\n const body = path.get(\"body\");\n\n // Concise arrow body: `() => <div />` or `() => cond ? <a/> : <b/>`\n if (!Array.isArray(body) && !body.isBlockStatement()) {\n const node = (body as NodePath).node;\n return containsJsx(node);\n }\n\n path.traverse({\n Function(inner) {\n inner.skip(); // JSX in a nested closure belongs to that closure\n },\n ReturnStatement(ret) {\n if (ret.node.argument && containsJsx(ret.node.argument)) found = true;\n },\n });\n return found;\n }\n\n function containsJsx(node: BabelTypes.Node | null | undefined): boolean {\n if (!node) return false;\n if (t.isJSXElement(node) || t.isJSXFragment(node)) return true;\n if (t.isConditionalExpression(node)) return containsJsx(node.consequent) || containsJsx(node.alternate);\n if (t.isLogicalExpression(node)) return containsJsx(node.left) || containsJsx(node.right);\n if (t.isParenthesizedExpression(node)) return containsJsx(node.expression);\n if (t.isCallExpression(node)) {\n // `memo(() => <div />)` and friends\n return node.arguments.some((a) => containsJsx(a as BabelTypes.Node));\n }\n return false;\n }\n\n function ensureImport(path: NodePath, state: State): BabelTypes.Identifier {\n if (state.rrdLocal) return state.rrdLocal;\n const program = path.findParent((p) => p.isProgram()) as NodePath<BabelTypes.Program>;\n const local = program.scope.generateUidIdentifier(\"rrdTrack\");\n const source = state.opts.importSource ?? DEFAULT_IMPORT_SOURCE;\n program.unshiftContainer(\n \"body\",\n t.importDeclaration([t.importSpecifier(local, t.identifier(\"withRenderDetective\"))], t.stringLiteral(source)),\n );\n state.rrdLocal = local;\n return local;\n }\n\n function ensureSelectorImport(path: NodePath, state: State): BabelTypes.Identifier {\n if (state.rrdTrackSelectorLocal) return state.rrdTrackSelectorLocal;\n const program = path.findParent((p) => p.isProgram()) as NodePath<BabelTypes.Program>;\n const local = program.scope.generateUidIdentifier(\"rrdTrackSelector\");\n const source = state.opts.importSource ?? DEFAULT_IMPORT_SOURCE;\n program.unshiftContainer(\n \"body\",\n t.importDeclaration([t.importSpecifier(local, t.identifier(\"trackSelector\"))], t.stringLiteral(source)),\n );\n state.rrdTrackSelectorLocal = local;\n return local;\n }\n\n /**\n * Derives a readable label from the selector expression.\n *\n * `state => state.flights.results` becomes `flights.results`, which is far\n * more useful in a diagnosis than a file and line. Anything less obvious\n * falls back to the call site.\n */\n function labelForSelector(argument: BabelTypes.Node | undefined): string | undefined {\n if (!argument) return undefined;\n if (!t.isArrowFunctionExpression(argument) && !t.isFunctionExpression(argument)) return undefined;\n const body = t.isBlockStatement(argument.body) ? undefined : argument.body;\n if (!body || !t.isMemberExpression(body)) return undefined;\n\n const parts: string[] = [];\n let current: BabelTypes.Node = body;\n while (t.isMemberExpression(current)) {\n if (t.isIdentifier(current.property)) parts.unshift(current.property.name);\n else if (t.isStringLiteral(current.property)) parts.unshift(current.property.value);\n else return undefined;\n current = current.object;\n }\n // Drop the state parameter itself: `state.a.b` → `a.b`.\n return t.isIdentifier(current) && parts.length > 0 ? parts.join(\".\") : undefined;\n }\n\n function locationOf(node: BabelTypes.Node, state: State): string | undefined {\n const line = node.loc?.start.line;\n if (line === undefined || !state.rrdRelativePath) return undefined;\n return `${state.rrdRelativePath}:${line}:${(node.loc?.start.column ?? 0) + 1}`;\n }\n\n /** `__rrdTrack(fn, { name, source })` */\n function wrap(\n fn: BabelTypes.Expression,\n name: string,\n node: BabelTypes.Node,\n path: NodePath,\n state: State,\n ): BabelTypes.CallExpression {\n const properties: BabelTypes.ObjectProperty[] = [\n t.objectProperty(t.identifier(\"name\"), t.stringLiteral(name)),\n ];\n const source = locationOf(node, state);\n if (source) properties.push(t.objectProperty(t.identifier(\"source\"), t.stringLiteral(source)));\n\n /*\n * Whether a component is declared inside another function is a *static*\n * fact, and the compiler is standing right here. The runtime previously\n * guessed at it by timing repeated definitions, which failed the moment a\n * user clicked more than five seconds apart.\n */\n if (path.getFunctionParent()) {\n properties.push(t.objectProperty(t.identifier(\"declaredInRender\"), t.booleanLiteral(true)));\n }\n state.rrdTouched = true;\n return t.callExpression(ensureImport(path, state), [fn, t.objectExpression(properties)]);\n }\n\n /** Already wrapped, by hand or by a previous pass. */\n function isAlreadyWrapped(path: NodePath): boolean {\n const parent = path.parentPath;\n if (!parent?.isCallExpression()) return false;\n const callee = parent.node.callee;\n if (t.isIdentifier(callee) && /rrdTrack|withRenderDetective/.test(callee.name)) return true;\n if (t.isMemberExpression(callee) && t.isIdentifier(callee.property, { name: \"withRenderDetective\" })) return true;\n return false;\n }\n\n return {\n name: \"react-render-detective\",\n\n pre(this: State, file: { opts: { filename?: string | null; root?: string | null } }) {\n const state = this;\n const filename = file.opts.filename ?? \"\";\n const root = state.opts.root ?? file.opts.root ?? process.cwd();\n state.rrdRelativePath = filename.startsWith(root) ? filename.slice(root.length).replace(/^[/\\\\]/, \"\") : filename;\n },\n\n visitor: {\n Program: {\n enter(path: NodePath<BabelTypes.Program>, state: State) {\n const enabled = state.opts.enabled ?? process.env.NODE_ENV !== \"production\";\n const filename = state.file.opts.filename ?? \"\";\n\n const skip =\n !enabled ||\n !filename ||\n /node_modules/.test(filename) ||\n SELF_PATTERN.test(filename) ||\n !matches(filename, state.opts.include, true) ||\n matches(filename, state.opts.exclude, false) ||\n (state.opts.clientOnly === true && !hasUseClient(path.node));\n\n if (skip) path.skip();\n },\n },\n\n /** Records which local names are bound to a tracked store hook. */\n ImportDeclaration(path: NodePath<BabelTypes.ImportDeclaration>, state: State) {\n if (state.opts.trackStores === false) return;\n const hooks = state.opts.storeHooks ?? DEFAULT_STORE_HOOKS;\n const wanted = hooks[path.node.source.value];\n if (!wanted) return;\n for (const specifier of path.node.specifiers) {\n if (!t.isImportSpecifier(specifier)) continue;\n const imported = t.isIdentifier(specifier.imported) ? specifier.imported.name : specifier.imported.value;\n if (wanted.includes(imported)) (state.rrdStoreHooks ??= new Set()).add(specifier.local.name);\n }\n },\n\n /**\n * `useSelector(fn)` → `_rrdTrackSelector(useSelector(fn), { name, source })`\n *\n * The call is wrapped rather than the import replaced, so every argument —\n * including react-redux's equality function — reaches the real hook\n * untouched. Changing those would change the app's behaviour.\n */\n CallExpression(path: NodePath<BabelTypes.CallExpression>, state: State) {\n if (state.opts.trackStores === false) return;\n if (!state.rrdStoreHooks || state.rrdStoreHooks.size === 0) return;\n if (processed.has(path.node)) return;\n\n const callee = path.node.callee;\n if (!t.isIdentifier(callee) || !state.rrdStoreHooks.has(callee.name)) return;\n // Not inside a component or hook body: nothing to attribute it to.\n if (!path.getFunctionParent()) return;\n\n processed.add(path.node);\n const source = locationOf(path.node, state);\n const label = labelForSelector(path.node.arguments[0] as BabelTypes.Node | undefined);\n\n const options: BabelTypes.ObjectProperty[] = [];\n if (label) options.push(t.objectProperty(t.identifier(\"name\"), t.stringLiteral(label)));\n if (source) options.push(t.objectProperty(t.identifier(\"source\"), t.stringLiteral(source)));\n\n state.rrdTouched = true;\n path.replaceWith(\n t.callExpression(ensureSelectorImport(path, state), [path.node, t.objectExpression(options)]),\n );\n },\n\n /** `function Foo() { return <div /> }` */\n FunctionDeclaration(path: NodePath<BabelTypes.FunctionDeclaration>, state: State) {\n const id = path.node.id;\n if (!id || !isComponentName(id.name)) return;\n if (!returnsJsx(path as NodePath<BabelTypes.Function>)) return;\n\n /*\n * Reassign rather than rewrite the declaration: function declarations\n * hoist, and components are routinely used above their definition. A\n * `const` would turn that into a temporal dead zone error at runtime.\n * ESM export bindings are live, so `export function Foo` still exports\n * the wrapper.\n */\n if (processed.has(path.node)) return;\n processed.add(path.node);\n\n const wrapped = wrap(t.cloneNode(id), id.name, path.node, path, state);\n const assignment = t.expressionStatement(t.assignmentExpression(\"=\", t.cloneNode(id), wrapped));\n (assignment as { _rrdGenerated?: boolean })._rrdGenerated = true;\n\n const statementParent = path.getStatementParent();\n if (path.parentPath.isExportDefaultDeclaration() || path.parentPath.isExportNamedDeclaration()) {\n statementParent?.insertAfter(assignment);\n } else {\n path.insertAfter(assignment);\n }\n },\n\n /** `const Foo = () => <div />` and `const Foo = memo(() => <div />)` */\n VariableDeclarator(path: NodePath<BabelTypes.VariableDeclarator>, state: State) {\n const id = path.node.id;\n const init = path.node.init;\n if (!t.isIdentifier(id) || !init || !isComponentName(id.name)) return;\n\n // Unwrap one level of memo()/forwardRef() so the instrumentation sits\n // inside them: memo compares props before our wrapper ever renders.\n let target: NodePath = path.get(\"init\") as NodePath;\n if (target.isCallExpression()) {\n const callee = target.node.callee;\n const isHoc =\n (t.isIdentifier(callee) && HOC_NAMES.has(callee.name)) ||\n (t.isMemberExpression(callee) && t.isIdentifier(callee.property) && HOC_NAMES.has(callee.property.name));\n if (!isHoc) return;\n const first = (target.get(\"arguments\") as NodePath[])[0];\n if (!first) return;\n target = first;\n }\n\n if (!target.isArrowFunctionExpression() && !target.isFunctionExpression()) return;\n if (isAlreadyWrapped(target)) return;\n if (!returnsJsx(target as NodePath<BabelTypes.Function>)) return;\n\n if (processed.has(path.node)) return;\n processed.add(path.node);\n target.replaceWith(wrap(target.node as BabelTypes.Expression, id.name, path.node, path, state));\n },\n\n /** `export default function () { return <div /> }` */\n ExportDefaultDeclaration(path: NodePath<BabelTypes.ExportDefaultDeclaration>, state: State) {\n const declaration = path.get(\"declaration\");\n if (!declaration.isFunctionDeclaration() || declaration.node.id) return; // named ones are handled above\n if (!returnsJsx(declaration as NodePath<BabelTypes.Function>)) return;\n\n const name = componentNameFromFile(state.rrdRelativePath ?? \"Default\");\n const expression = t.functionExpression(\n null,\n declaration.node.params as BabelTypes.Identifier[],\n declaration.node.body,\n declaration.node.generator,\n declaration.node.async,\n );\n if (processed.has(path.node)) return;\n processed.add(path.node);\n path.replaceWith(t.exportDefaultDeclaration(wrap(expression, name, declaration.node, path, state)));\n },\n },\n };\n}\n\nfunction matches(filename: string, patterns: Array<string | RegExp> | undefined, whenEmpty: boolean): boolean {\n if (!patterns || patterns.length === 0) return whenEmpty;\n return patterns.some((p) => (typeof p === \"string\" ? filename.includes(p) : p.test(filename)));\n}\n\nfunction hasUseClient(program: BabelTypes.Program): boolean {\n return program.directives.some((d) => d.value.value === \"use client\");\n}\n\n/** `src/components/UserCard.tsx` → `UserCard` */\nfunction componentNameFromFile(path: string): string {\n const base = path.split(/[/\\\\]/).pop() ?? \"Default\";\n const stem = base.replace(/\\.[jt]sx?$/, \"\");\n const cleaned = stem === \"index\" ? (path.split(/[/\\\\]/).slice(-2)[0] ?? \"Default\") : stem;\n const pascal = cleaned.replace(/(^|[-_.])(\\w)/g, (_, __, c: string) => c.toUpperCase());\n return /^[A-Z]/.test(pascal) ? pascal : `Component${pascal}`;\n}\n"]}
|
|
@@ -8,6 +8,7 @@ function explainEvents(component, events, lifecycle) {
|
|
|
8
8
|
const denominator = updates.length || mine.length;
|
|
9
9
|
const reasonCounts = /* @__PURE__ */ new Map();
|
|
10
10
|
const unstable = /* @__PURE__ */ new Map();
|
|
11
|
+
const unstableSelector = /* @__PURE__ */ new Map();
|
|
11
12
|
let totalSelf = 0;
|
|
12
13
|
let avoidable = 0;
|
|
13
14
|
let avoidableTime = 0;
|
|
@@ -26,6 +27,12 @@ function explainEvents(component, events, lifecycle) {
|
|
|
26
27
|
if (e.changedProps.some((c) => c.kind !== "reference")) propsWithNewValues++;
|
|
27
28
|
else propsReferenceOnly++;
|
|
28
29
|
}
|
|
30
|
+
for (const c of e.selectorChanges) {
|
|
31
|
+
if (!c.referenceOnly) continue;
|
|
32
|
+
const entry = unstableSelector.get(c.name) ?? { count: 0, source: c.source };
|
|
33
|
+
entry.count++;
|
|
34
|
+
unstableSelector.set(c.name, entry);
|
|
35
|
+
}
|
|
29
36
|
for (const c of e.changedProps) {
|
|
30
37
|
if (c.kind !== "reference") continue;
|
|
31
38
|
const entry = unstable.get(c.key) ?? { count: 0, valueType: c.valueType };
|
|
@@ -34,9 +41,11 @@ function explainEvents(component, events, lifecycle) {
|
|
|
34
41
|
}
|
|
35
42
|
}
|
|
36
43
|
const breakdown = [...reasonCounts.entries()].map(([reason, count]) => ({ reason, count, share: count / mine.length })).sort((a, b) => b.count - a.count);
|
|
44
|
+
const unstableSelectors = [...unstableSelector.entries()].map(([name, v]) => ({ name, source: v.source, count: v.count, share: v.count / denominator })).sort((a, b) => b.count - a.count);
|
|
37
45
|
const unstableProps = [...unstable.entries()].map(([key, v]) => ({ key, count: v.count, share: v.count / denominator, valueType: v.valueType })).sort((a, b) => b.count - a.count);
|
|
38
46
|
const top = [...reasonCounts.entries()].filter(([reason]) => reason !== "mount").map(([reason, count]) => ({ reason, count, share: count / denominator })).sort((a, b) => b.count - a.count)[0];
|
|
39
47
|
const topProp = unstableProps[0];
|
|
48
|
+
const topSelector = unstableSelectors[0];
|
|
40
49
|
const latest = mine[mine.length - 1];
|
|
41
50
|
let headline;
|
|
42
51
|
let nextStep;
|
|
@@ -47,6 +56,10 @@ function explainEvents(component, events, lifecycle) {
|
|
|
47
56
|
headline = `${component} was rebuilt ${remounts}\xD7 rather than re-rendered \u2014 its DOM and state were discarded each time.`;
|
|
48
57
|
nextStep = mountEvent?.diagnosis.suggestion ?? `Check whether ${component} is declared inside another component's render body, or receives a changing \`key\`.`;
|
|
49
58
|
confidence = mountEvent?.diagnosis.confidence ?? "medium";
|
|
59
|
+
} else if (topSelector && topSelector.share >= 0.5) {
|
|
60
|
+
headline = `${pct(topSelector.share)} of updates followed the \`${topSelector.name}\` selector returning a new reference with identical contents \u2014 so this re-renders on every store update, not only when its data changes.`;
|
|
61
|
+
nextStep = `Make \`${topSelector.name}\`${topSelector.source ? ` at ${topSelector.source}` : ""} return a stable value: select the raw slice and derive outside the selector, memoize with createSelector, or pass shallowEqual.`;
|
|
62
|
+
confidence = "high";
|
|
50
63
|
} else if (topProp && topProp.share >= 0.5) {
|
|
51
64
|
headline = `${pct(topProp.share)} of updates followed \`${topProp.key}\` changing by reference while its contents stayed the same.`;
|
|
52
65
|
const via = latest.parent?.name;
|
|
@@ -61,6 +74,10 @@ function explainEvents(component, events, lifecycle) {
|
|
|
61
74
|
headline = `${pct(top.share)} of updates followed a tracked context update.`;
|
|
62
75
|
nextStep = "Check whether the provider's value is stable, and whether this component needs the whole context value.";
|
|
63
76
|
confidence = "medium";
|
|
77
|
+
} else if (top && top.reason === "store") {
|
|
78
|
+
headline = `${pct(top.share)} of updates came from tracked store selectors whose values genuinely changed.`;
|
|
79
|
+
nextStep = "These are real data changes. Look at what each render costs rather than how many there are, or select less per component so fewer components wake on each store update.";
|
|
80
|
+
confidence = "high";
|
|
64
81
|
} else if (top && (top.reason === "state" || top.reason === "state-or-external")) {
|
|
65
82
|
headline = `${pct(top.share)} of updates came from inside the component \u2014 state or an external store.`;
|
|
66
83
|
nextStep = top.reason === "state" ? "These are real state updates. Check whether every update needs to change state." : "Name the state with useTrackedState to see which value drives these renders.";
|
|
@@ -94,6 +111,7 @@ function explainEvents(component, events, lifecycle) {
|
|
|
94
111
|
unstableProps,
|
|
95
112
|
averageSelfDuration: totalSelf / mine.length,
|
|
96
113
|
totalSelfDuration: totalSelf,
|
|
114
|
+
unstableSelectors,
|
|
97
115
|
potentiallyAvoidableRenders: avoidable,
|
|
98
116
|
estimatedAvoidableTime: avoidableTime,
|
|
99
117
|
devReplays: replays,
|
|
@@ -115,6 +133,12 @@ function formatExplanation(e) {
|
|
|
115
133
|
"Breakdown (share of all renders)",
|
|
116
134
|
...e.breakdown.map((b) => ` ${b.reason.padEnd(18)} ${String(b.count).padStart(5)} ${pct(b.share)}`)
|
|
117
135
|
];
|
|
136
|
+
if (e.unstableSelectors.length > 0) {
|
|
137
|
+
lines.push("", "Selectors returning a new reference each call (share of updates)");
|
|
138
|
+
for (const sel of e.unstableSelectors) {
|
|
139
|
+
lines.push(` ${sel.name.padEnd(24)} ${String(sel.count).padStart(5)} ${pct(sel.share)}${sel.source ? ` ${sel.source}` : ""}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
118
142
|
if (e.unstableProps.length > 0) {
|
|
119
143
|
lines.push("", "Reference-only prop changes (share of updates)");
|
|
120
144
|
for (const p of e.unstableProps) {
|
|
@@ -145,5 +169,5 @@ var fmt = (ms) => `${ms.toFixed(1)}ms`;
|
|
|
145
169
|
|
|
146
170
|
exports.explainEvents = explainEvents;
|
|
147
171
|
exports.formatExplanation = formatExplanation;
|
|
148
|
-
//# sourceMappingURL=chunk-
|
|
149
|
-
//# sourceMappingURL=chunk-
|
|
172
|
+
//# sourceMappingURL=chunk-RGT44QQI.cjs.map
|
|
173
|
+
//# sourceMappingURL=chunk-RGT44QQI.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/explain.ts"],"names":[],"mappings":"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","file":"chunk-RGT44QQI.cjs","sourcesContent":["import type { Confidence, RenderEvent, RenderReason } from \"./types.js\";\n\nexport interface Explanation {\n component: string;\n /** `File.tsx:12:2`, when the build plugin instrumented this component. */\n source?: string;\n /** Where the component's props come from, and its source if known. */\n parent?: { name: string; source?: string };\n renders: number;\n /** Mounts are excluded from every share below — they cannot be optimised away. */\n mounts: number;\n /** Reason → share of renders, descending. */\n breakdown: Array<{ reason: RenderReason; count: number; share: number }>;\n /** Props that most often changed by reference only, descending. */\n unstableProps: Array<{ key: string; count: number; share: number; valueType: string }>;\n /** Store selectors that returned a new reference with identical contents. */\n unstableSelectors: Array<{ name: string; source?: string; count: number; share: number }>;\n averageSelfDuration: number;\n totalSelfDuration: number;\n potentiallyAvoidableRenders: number;\n estimatedAvoidableTime: number;\n devReplays: number;\n /** Times the component was rebuilt rather than re-rendered. */\n remounts: number;\n headline: string;\n nextStep: string;\n confidence: Confidence;\n}\n\n/**\n * The flagship \"explain this render\" answer, aggregated across the recorded\n * history of one component. Pure — no React, no console.\n */\nexport function explainEvents(\n component: string,\n events: RenderEvent[],\n lifecycle?: { remounts: number },\n): Explanation | undefined {\n const mine = events.filter((e) => e.component.name === component);\n if (mine.length === 0) return undefined;\n\n /*\n * Shares are measured against *updates*, not against every recorded render.\n * Mounts happen once per instance and are not something you can optimise\n * away, so counting them in the denominator quietly deflates the share of\n * whatever is actually driving the re-renders — on a 20-row list, a prop\n * responsible for every single update reads as \"33%\".\n */\n const updates = mine.filter((e) => e.phase !== \"mount\");\n const denominator = updates.length || mine.length;\n\n const reasonCounts = new Map<RenderReason, number>();\n const unstable = new Map<string, { count: number; valueType: string }>();\n const unstableSelector = new Map<string, { count: number; source?: string }>();\n let totalSelf = 0;\n let avoidable = 0;\n let avoidableTime = 0;\n let replays = 0;\n let propsWithNewValues = 0;\n let propsReferenceOnly = 0;\n\n for (const e of mine) {\n reasonCounts.set(e.diagnosis.reason, (reasonCounts.get(e.diagnosis.reason) ?? 0) + 1);\n totalSelf += e.timings.selfDuration;\n if (e.devReplay) replays++;\n if (e.diagnosis.potentiallyAvoidable) {\n avoidable++;\n avoidableTime += e.timings.selfDuration;\n }\n if (e.diagnosis.reason === \"props\") {\n if (e.changedProps.some((c) => c.kind !== \"reference\")) propsWithNewValues++;\n else propsReferenceOnly++;\n }\n for (const c of e.selectorChanges) {\n if (!c.referenceOnly) continue;\n const entry = unstableSelector.get(c.name) ?? { count: 0, source: c.source };\n entry.count++;\n unstableSelector.set(c.name, entry);\n }\n for (const c of e.changedProps) {\n if (c.kind !== \"reference\") continue;\n const entry = unstable.get(c.key) ?? { count: 0, valueType: c.valueType };\n entry.count++;\n unstable.set(c.key, entry);\n }\n }\n\n const breakdown = [...reasonCounts.entries()]\n .map(([reason, count]) => ({ reason, count, share: count / mine.length }))\n .sort((a, b) => b.count - a.count);\n\n const unstableSelectors = [...unstableSelector.entries()]\n .map(([name, v]) => ({ name, source: v.source, count: v.count, share: v.count / denominator }))\n .sort((a, b) => b.count - a.count);\n\n const unstableProps = [...unstable.entries()]\n .map(([key, v]) => ({ key, count: v.count, share: v.count / denominator, valueType: v.valueType }))\n .sort((a, b) => b.count - a.count);\n\n // Ranked over updates, for the same reason the shares are.\n const top = [...reasonCounts.entries()]\n .filter(([reason]) => reason !== \"mount\")\n .map(([reason, count]) => ({ reason, count, share: count / denominator }))\n .sort((a, b) => b.count - a.count)[0];\n const topProp = unstableProps[0];\n const topSelector = unstableSelectors[0];\n const latest = mine[mine.length - 1] as RenderEvent;\n\n let headline: string;\n let nextStep: string;\n let confidence: Confidence = \"medium\";\n\n const remounts = lifecycle?.remounts ?? 0;\n\n /*\n * Remounts outrank every render explanation. A component being rebuilt is\n * throwing away its DOM and its state, which costs more than any number of\n * re-renders — so if that is happening, it is the headline.\n */\n if (remounts >= 2) {\n const mountEvent = [...mine].reverse().find((e) => e.phase === \"mount\");\n headline = `${component} was rebuilt ${remounts}× rather than re-rendered — its DOM and state were discarded each time.`;\n nextStep =\n mountEvent?.diagnosis.suggestion ??\n `Check whether ${component} is declared inside another component's render body, or receives a changing \\`key\\`.`;\n confidence = mountEvent?.diagnosis.confidence ?? \"medium\";\n } else if (topSelector && topSelector.share >= 0.5) {\n /*\n * Ranked above props: a selector rebuilding its value re-renders the\n * component on *every* store update, so it is usually the larger cause.\n */\n headline =\n `${pct(topSelector.share)} of updates followed the \\`${topSelector.name}\\` selector returning a new reference ` +\n `with identical contents — so this re-renders on every store update, not only when its data changes.`;\n nextStep =\n `Make \\`${topSelector.name}\\`${topSelector.source ? ` at ${topSelector.source}` : \"\"} return a stable value: ` +\n `select the raw slice and derive outside the selector, memoize with createSelector, or pass shallowEqual.`;\n confidence = \"high\";\n } else if (topProp && topProp.share >= 0.5) {\n headline = `${pct(topProp.share)} of updates followed \\`${topProp.key}\\` changing by reference while its contents stayed the same.`;\n // `parent` is the nearest instrumented ancestor — where the prop arrives\n // from, which is not necessarily where it is created. Say the former.\n const via = latest.parent?.name;\n const viaSource = latest.parent?.source ? ` (${latest.parent.source})` : \"\";\n nextStep =\n `Trace \\`${topProp.key}\\` back from ${via ? `${via}${viaSource}, which passes it to ${component}` : component}, ` +\n `and stabilise it where it is created${\n topProp.valueType === \"function\" ? \" (useCallback, or hoist it out of the component)\" : \" (useMemo, or pass the primitive fields you use)\"\n }.`;\n confidence = \"high\";\n } else if (top && top.reason === \"parent\" && top.share >= 0.5) {\n headline = `${pct(top.share)} of updates were parent propagation with identical props.`;\n nextStep = `Measure ${component} with React.memo(). It is only worth it if ${fmt(totalSelf / mine.length)} per render matters here.`;\n confidence = \"high\";\n } else if (top && top.reason === \"context\") {\n headline = `${pct(top.share)} of updates followed a tracked context update.`;\n nextStep = \"Check whether the provider's value is stable, and whether this component needs the whole context value.\";\n confidence = \"medium\";\n } else if (top && top.reason === \"store\") {\n headline = `${pct(top.share)} of updates came from tracked store selectors whose values genuinely changed.`;\n nextStep =\n \"These are real data changes. Look at what each render costs rather than how many there are, \" +\n \"or select less per component so fewer components wake on each store update.\";\n confidence = \"high\";\n } else if (top && (top.reason === \"state\" || top.reason === \"state-or-external\")) {\n headline = `${pct(top.share)} of updates came from inside the component — state or an external store.`;\n nextStep =\n top.reason === \"state\"\n ? \"These are real state updates. Check whether every update needs to change state.\"\n : \"Name the state with useTrackedState to see which value drives these renders.\";\n confidence = top.reason === \"state\" ? \"high\" : \"medium\";\n } else if (top && top.reason === \"props\") {\n // Do not call a bucket \"new values\" without checking that it holds any.\n if (propsReferenceOnly > propsWithNewValues) {\n headline = `${pct(propsReferenceOnly / denominator)} of updates were prop changes where only the reference changed — the contents were identical.`;\n nextStep = `Stabilise the props listed above in whichever component renders ${component}.`;\n confidence = \"high\";\n } else if (propsReferenceOnly > 0) {\n headline =\n `${pct(propsWithNewValues / denominator)} of updates carried genuinely new prop values, ` +\n `and ${pct(propsReferenceOnly / denominator)} changed by reference only.`;\n nextStep = \"The reference-only ones are the avoidable half — start there.\";\n confidence = \"high\";\n } else {\n headline = `${pct(top.share)} of updates were driven by props with genuinely new values.`;\n nextStep = \"These look like legitimate data changes. Look at render cost rather than render count.\";\n confidence = \"high\";\n }\n } else {\n headline = \"Cause could not be determined reliably.\";\n nextStep = \"Instrument the parent, or track the context this component consumes, to narrow it down.\";\n confidence = \"low\";\n }\n\n return {\n component,\n source: latest.component.source,\n parent: latest.parent ? { name: latest.parent.name, source: latest.parent.source } : undefined,\n renders: mine.length,\n mounts: mine.length - updates.length,\n breakdown,\n unstableProps,\n averageSelfDuration: totalSelf / mine.length,\n totalSelfDuration: totalSelf,\n unstableSelectors,\n potentiallyAvoidableRenders: avoidable,\n estimatedAvoidableTime: avoidableTime,\n devReplays: replays,\n remounts,\n headline,\n nextStep,\n confidence,\n };\n}\n\nexport function formatExplanation(e: Explanation): string {\n const lines: string[] = [\n e.source ? `${e.component} ${e.source}` : `${e.component}`,\n \"\",\n `${e.renders} recorded render${e.renders === 1 ? \"\" : \"s\"}${e.mounts > 0 ? ` (${e.mounts} mount${e.mounts === 1 ? \"\" : \"s\"})` : \"\"}`,\n \"\",\n \"Why?\",\n ` ${e.headline}`,\n \"\",\n \"Breakdown (share of all renders)\",\n ...e.breakdown.map((b) => ` ${b.reason.padEnd(18)} ${String(b.count).padStart(5)} ${pct(b.share)}`),\n ];\n\n if (e.unstableSelectors.length > 0) {\n lines.push(\"\", \"Selectors returning a new reference each call (share of updates)\");\n for (const sel of e.unstableSelectors) {\n lines.push(` ${sel.name.padEnd(24)} ${String(sel.count).padStart(5)} ${pct(sel.share)}${sel.source ? ` ${sel.source}` : \"\"}`);\n }\n }\n\n if (e.unstableProps.length > 0) {\n lines.push(\"\", \"Reference-only prop changes (share of updates)\");\n for (const p of e.unstableProps) {\n lines.push(` ${p.key.padEnd(18)} ${String(p.count).padStart(5)} ${pct(p.share)} (${p.valueType})`);\n }\n }\n\n if (e.remounts > 0) {\n lines.push(\"\", `Rebuilt ${e.remounts}× (unmounted and mounted again — state and DOM discarded)`);\n }\n\n lines.push(\n \"\",\n \"Cost\",\n ` average ${fmt(e.averageSelfDuration)}`,\n ` total ${fmt(e.totalSelfDuration)}`,\n ` potentially avoidable ${e.potentiallyAvoidableRenders} render(s), ~${fmt(e.estimatedAvoidableTime)}`,\n );\n\n if (e.devReplays > 0) {\n lines.push(\n \"\",\n ` ${e.devReplays} development replay(s) observed (StrictMode double-invoke or discarded attempts) — excluded from the counts above.`,\n );\n }\n\n lines.push(\"\", \"Next step\", ` ${e.nextStep}`, \"\", `Confidence: ${e.confidence}`);\n return lines.join(\"\\n\");\n}\n\nconst pct = (n: number): string => `${Math.round(n * 100)}%`;\nconst fmt = (ms: number): string => `${ms.toFixed(1)}ms`;\n"]}
|
package/dist/core.cjs
CHANGED
|
@@ -1,76 +1,76 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkLCGXVRJR_cjs = require('./chunk-LCGXVRJR.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
Object.defineProperty(exports, "Detective", {
|
|
8
8
|
enumerable: true,
|
|
9
|
-
get: function () { return
|
|
9
|
+
get: function () { return chunkLCGXVRJR_cjs.Detective; }
|
|
10
10
|
});
|
|
11
11
|
Object.defineProperty(exports, "RingBuffer", {
|
|
12
12
|
enumerable: true,
|
|
13
|
-
get: function () { return
|
|
13
|
+
get: function () { return chunkLCGXVRJR_cjs.RingBuffer; }
|
|
14
14
|
});
|
|
15
15
|
Object.defineProperty(exports, "defaultConfig", {
|
|
16
16
|
enumerable: true,
|
|
17
|
-
get: function () { return
|
|
17
|
+
get: function () { return chunkLCGXVRJR_cjs.defaultConfig; }
|
|
18
18
|
});
|
|
19
19
|
Object.defineProperty(exports, "detectDev", {
|
|
20
20
|
enumerable: true,
|
|
21
|
-
get: function () { return
|
|
21
|
+
get: function () { return chunkLCGXVRJR_cjs.detectDev; }
|
|
22
22
|
});
|
|
23
23
|
Object.defineProperty(exports, "diagnose", {
|
|
24
24
|
enumerable: true,
|
|
25
|
-
get: function () { return
|
|
25
|
+
get: function () { return chunkLCGXVRJR_cjs.diagnose; }
|
|
26
26
|
});
|
|
27
27
|
Object.defineProperty(exports, "diffProps", {
|
|
28
28
|
enumerable: true,
|
|
29
|
-
get: function () { return
|
|
29
|
+
get: function () { return chunkLCGXVRJR_cjs.diffProps; }
|
|
30
30
|
});
|
|
31
31
|
Object.defineProperty(exports, "formatInspected", {
|
|
32
32
|
enumerable: true,
|
|
33
|
-
get: function () { return
|
|
33
|
+
get: function () { return chunkLCGXVRJR_cjs.formatInspected; }
|
|
34
34
|
});
|
|
35
35
|
Object.defineProperty(exports, "getDetective", {
|
|
36
36
|
enumerable: true,
|
|
37
|
-
get: function () { return
|
|
37
|
+
get: function () { return chunkLCGXVRJR_cjs.getDetective; }
|
|
38
38
|
});
|
|
39
39
|
Object.defineProperty(exports, "inspect", {
|
|
40
40
|
enumerable: true,
|
|
41
|
-
get: function () { return
|
|
41
|
+
get: function () { return chunkLCGXVRJR_cjs.inspect; }
|
|
42
42
|
});
|
|
43
43
|
Object.defineProperty(exports, "isPlainObject", {
|
|
44
44
|
enumerable: true,
|
|
45
|
-
get: function () { return
|
|
45
|
+
get: function () { return chunkLCGXVRJR_cjs.isPlainObject; }
|
|
46
46
|
});
|
|
47
47
|
Object.defineProperty(exports, "isReactElement", {
|
|
48
48
|
enumerable: true,
|
|
49
|
-
get: function () { return
|
|
49
|
+
get: function () { return chunkLCGXVRJR_cjs.isReactElement; }
|
|
50
50
|
});
|
|
51
51
|
Object.defineProperty(exports, "matches", {
|
|
52
52
|
enumerable: true,
|
|
53
|
-
get: function () { return
|
|
53
|
+
get: function () { return chunkLCGXVRJR_cjs.matches; }
|
|
54
54
|
});
|
|
55
55
|
Object.defineProperty(exports, "mergeConfig", {
|
|
56
56
|
enumerable: true,
|
|
57
|
-
get: function () { return
|
|
57
|
+
get: function () { return chunkLCGXVRJR_cjs.mergeConfig; }
|
|
58
58
|
});
|
|
59
59
|
Object.defineProperty(exports, "severityFor", {
|
|
60
60
|
enumerable: true,
|
|
61
|
-
get: function () { return
|
|
61
|
+
get: function () { return chunkLCGXVRJR_cjs.severityFor; }
|
|
62
62
|
});
|
|
63
63
|
Object.defineProperty(exports, "shallowEqual", {
|
|
64
64
|
enumerable: true,
|
|
65
|
-
get: function () { return
|
|
65
|
+
get: function () { return chunkLCGXVRJR_cjs.shallowEqual; }
|
|
66
66
|
});
|
|
67
67
|
Object.defineProperty(exports, "shouldInstrument", {
|
|
68
68
|
enumerable: true,
|
|
69
|
-
get: function () { return
|
|
69
|
+
get: function () { return chunkLCGXVRJR_cjs.shouldInstrument; }
|
|
70
70
|
});
|
|
71
71
|
Object.defineProperty(exports, "valueType", {
|
|
72
72
|
enumerable: true,
|
|
73
|
-
get: function () { return
|
|
73
|
+
get: function () { return chunkLCGXVRJR_cjs.valueType; }
|
|
74
74
|
});
|
|
75
75
|
//# sourceMappingURL=core.cjs.map
|
|
76
76
|
//# sourceMappingURL=core.cjs.map
|
package/dist/core.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { D as DetectiveConfig, T as TrackedStateChange, R as RenderReason, a as DetectiveOptions, b as RenderEvent, c as RenderPhase, C as ContextChange, d as ComponentStats, A as AppStats, P as PropChange, e as Thresholds, f as Diagnosis, I as Inspected, g as InspectionLimits, h as PropValueType } from './types-
|
|
2
|
-
export { i as ComponentInfo, j as Confidence, M as Mode, k as PropChangeKind, l as RenderTimings } from './types-
|
|
1
|
+
import { D as DetectiveConfig, T as TrackedStateChange, S as SelectorChange, R as RenderReason, a as DetectiveOptions, b as RenderEvent, c as RenderPhase, C as ContextChange, d as ComponentStats, A as AppStats, P as PropChange, e as Thresholds, f as Diagnosis, I as Inspected, g as InspectionLimits, h as PropValueType } from './types-CRET8EhB.cjs';
|
|
2
|
+
export { i as ComponentInfo, j as Confidence, M as Mode, k as PropChangeKind, l as RenderTimings } from './types-CRET8EhB.cjs';
|
|
3
3
|
|
|
4
4
|
/** What an instrumentation site reports at commit time. */
|
|
5
5
|
interface CommitInput {
|
|
@@ -15,6 +15,8 @@ interface Lifecycle {
|
|
|
15
15
|
unmounts: number;
|
|
16
16
|
/** Mounts that followed an unmount of the same component. */
|
|
17
17
|
remounts: number;
|
|
18
|
+
/** When the most recent remount was observed. */
|
|
19
|
+
lastRemountAt?: number;
|
|
18
20
|
}
|
|
19
21
|
interface NodeRecord {
|
|
20
22
|
id: string;
|
|
@@ -32,6 +34,8 @@ interface NodeRecord {
|
|
|
32
34
|
attempts: number;
|
|
33
35
|
/** Named state updates reported by `useTrackedState`, consumed at the next commit. */
|
|
34
36
|
pendingState: TrackedStateChange[];
|
|
37
|
+
/** Selector value changes reported by tracked `useSelector`, consumed at the next commit. */
|
|
38
|
+
pendingSelectors: SelectorChange[];
|
|
35
39
|
/** Set as soon as a commit is queued, so mount detection never waits on flush. */
|
|
36
40
|
seenCommit: boolean;
|
|
37
41
|
/** Has this instance ever been attached? Distinguishes a real mount from a StrictMode replay. */
|
|
@@ -64,6 +68,9 @@ declare class Detective {
|
|
|
64
68
|
private nodes;
|
|
65
69
|
private events;
|
|
66
70
|
private listeners;
|
|
71
|
+
/** Registered by optional entry points so they follow clear()/reset() without being imported here. */
|
|
72
|
+
private clearHooks;
|
|
73
|
+
private resetHooks;
|
|
67
74
|
private pending;
|
|
68
75
|
private contextChanges;
|
|
69
76
|
/** Orders renders and context updates so they can be matched without timers. */
|
|
@@ -91,6 +98,8 @@ declare class Detective {
|
|
|
91
98
|
configure(options?: DetectiveOptions): void;
|
|
92
99
|
get isInitialized(): boolean;
|
|
93
100
|
get enabled(): boolean;
|
|
101
|
+
registerClearHook(hook: () => void): void;
|
|
102
|
+
registerResetHook(hook: () => void): void;
|
|
94
103
|
subscribe(listener: (event: RenderEvent) => void): () => void;
|
|
95
104
|
/**
|
|
96
105
|
* Creates a node without publishing it. StrictMode's double mount renders
|
|
@@ -118,9 +127,20 @@ declare class Detective {
|
|
|
118
127
|
*/
|
|
119
128
|
inlineDefinitionSuspected(name: string): boolean;
|
|
120
129
|
lifecycleOf(name: string): Lifecycle;
|
|
130
|
+
/**
|
|
131
|
+
* Did a whole-tree rebuild just happen?
|
|
132
|
+
*
|
|
133
|
+
* Hot reload is the most common cause of remounts in development, and this
|
|
134
|
+
* tool only ever runs in development — so without this it would confidently
|
|
135
|
+
* blame a `key` every time React Fast Refresh replaced a module. A real key
|
|
136
|
+
* or inline-definition problem affects one component; a reload affects many
|
|
137
|
+
* at once.
|
|
138
|
+
*/
|
|
139
|
+
private reloadSuspectedAt;
|
|
121
140
|
/** Hot path. Must stay allocation-free and O(1). */
|
|
122
141
|
recordAttempt(node: NodeRecord, props: Record<string, unknown>): void;
|
|
123
142
|
recordStateChange(node: NodeRecord, change: TrackedStateChange): void;
|
|
143
|
+
recordSelectorChange(node: NodeRecord, change: SelectorChange): void;
|
|
124
144
|
/**
|
|
125
145
|
* Hot path. Called from Profiler#onRender; only enqueues.
|
|
126
146
|
*
|
|
@@ -192,10 +212,14 @@ interface DiagnosisInput {
|
|
|
192
212
|
contextChanges: ContextChange[];
|
|
193
213
|
/** Named state updates from `useTrackedState`. Empty unless opted in. */
|
|
194
214
|
trackedState: TrackedStateChange[];
|
|
215
|
+
/** External-store selector values that changed. Empty unless selectors are tracked. */
|
|
216
|
+
selectorChanges: SelectorChange[];
|
|
195
217
|
/** How many times this component has been rebuilt rather than re-rendered. */
|
|
196
218
|
remounts: number;
|
|
197
219
|
/** The component looks like it is declared inside another component's render body. */
|
|
198
220
|
inlineDefinitionSuspected: boolean;
|
|
221
|
+
/** Many components remounted at once — a hot reload or a route change. */
|
|
222
|
+
treeReloadSuspected: boolean;
|
|
199
223
|
selfDuration: number;
|
|
200
224
|
attempts: number;
|
|
201
225
|
committed: boolean;
|
|
@@ -236,4 +260,4 @@ declare class RingBuffer<T> {
|
|
|
236
260
|
resize(capacity: number): void;
|
|
237
261
|
}
|
|
238
262
|
|
|
239
|
-
export { AppStats, ComponentStats, ContextChange, Detective, DetectiveConfig, DetectiveOptions, Diagnosis, type DiagnosisInput, Inspected, InspectionLimits, PropChange, PropValueType, RenderEvent, RenderPhase, RenderReason, RingBuffer, Thresholds, TrackedStateChange, defaultConfig, detectDev, diagnose, diffProps, formatInspected, getDetective, inspect, isPlainObject, isReactElement, matches, mergeConfig, severityFor, shallowEqual, shouldInstrument, valueType };
|
|
263
|
+
export { AppStats, ComponentStats, ContextChange, Detective, DetectiveConfig, DetectiveOptions, Diagnosis, type DiagnosisInput, Inspected, InspectionLimits, PropChange, PropValueType, RenderEvent, RenderPhase, RenderReason, RingBuffer, SelectorChange, Thresholds, TrackedStateChange, defaultConfig, detectDev, diagnose, diffProps, formatInspected, getDetective, inspect, isPlainObject, isReactElement, matches, mergeConfig, severityFor, shallowEqual, shouldInstrument, valueType };
|
package/dist/core.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { D as DetectiveConfig, T as TrackedStateChange, R as RenderReason, a as DetectiveOptions, b as RenderEvent, c as RenderPhase, C as ContextChange, d as ComponentStats, A as AppStats, P as PropChange, e as Thresholds, f as Diagnosis, I as Inspected, g as InspectionLimits, h as PropValueType } from './types-
|
|
2
|
-
export { i as ComponentInfo, j as Confidence, M as Mode, k as PropChangeKind, l as RenderTimings } from './types-
|
|
1
|
+
import { D as DetectiveConfig, T as TrackedStateChange, S as SelectorChange, R as RenderReason, a as DetectiveOptions, b as RenderEvent, c as RenderPhase, C as ContextChange, d as ComponentStats, A as AppStats, P as PropChange, e as Thresholds, f as Diagnosis, I as Inspected, g as InspectionLimits, h as PropValueType } from './types-CRET8EhB.js';
|
|
2
|
+
export { i as ComponentInfo, j as Confidence, M as Mode, k as PropChangeKind, l as RenderTimings } from './types-CRET8EhB.js';
|
|
3
3
|
|
|
4
4
|
/** What an instrumentation site reports at commit time. */
|
|
5
5
|
interface CommitInput {
|
|
@@ -15,6 +15,8 @@ interface Lifecycle {
|
|
|
15
15
|
unmounts: number;
|
|
16
16
|
/** Mounts that followed an unmount of the same component. */
|
|
17
17
|
remounts: number;
|
|
18
|
+
/** When the most recent remount was observed. */
|
|
19
|
+
lastRemountAt?: number;
|
|
18
20
|
}
|
|
19
21
|
interface NodeRecord {
|
|
20
22
|
id: string;
|
|
@@ -32,6 +34,8 @@ interface NodeRecord {
|
|
|
32
34
|
attempts: number;
|
|
33
35
|
/** Named state updates reported by `useTrackedState`, consumed at the next commit. */
|
|
34
36
|
pendingState: TrackedStateChange[];
|
|
37
|
+
/** Selector value changes reported by tracked `useSelector`, consumed at the next commit. */
|
|
38
|
+
pendingSelectors: SelectorChange[];
|
|
35
39
|
/** Set as soon as a commit is queued, so mount detection never waits on flush. */
|
|
36
40
|
seenCommit: boolean;
|
|
37
41
|
/** Has this instance ever been attached? Distinguishes a real mount from a StrictMode replay. */
|
|
@@ -64,6 +68,9 @@ declare class Detective {
|
|
|
64
68
|
private nodes;
|
|
65
69
|
private events;
|
|
66
70
|
private listeners;
|
|
71
|
+
/** Registered by optional entry points so they follow clear()/reset() without being imported here. */
|
|
72
|
+
private clearHooks;
|
|
73
|
+
private resetHooks;
|
|
67
74
|
private pending;
|
|
68
75
|
private contextChanges;
|
|
69
76
|
/** Orders renders and context updates so they can be matched without timers. */
|
|
@@ -91,6 +98,8 @@ declare class Detective {
|
|
|
91
98
|
configure(options?: DetectiveOptions): void;
|
|
92
99
|
get isInitialized(): boolean;
|
|
93
100
|
get enabled(): boolean;
|
|
101
|
+
registerClearHook(hook: () => void): void;
|
|
102
|
+
registerResetHook(hook: () => void): void;
|
|
94
103
|
subscribe(listener: (event: RenderEvent) => void): () => void;
|
|
95
104
|
/**
|
|
96
105
|
* Creates a node without publishing it. StrictMode's double mount renders
|
|
@@ -118,9 +127,20 @@ declare class Detective {
|
|
|
118
127
|
*/
|
|
119
128
|
inlineDefinitionSuspected(name: string): boolean;
|
|
120
129
|
lifecycleOf(name: string): Lifecycle;
|
|
130
|
+
/**
|
|
131
|
+
* Did a whole-tree rebuild just happen?
|
|
132
|
+
*
|
|
133
|
+
* Hot reload is the most common cause of remounts in development, and this
|
|
134
|
+
* tool only ever runs in development — so without this it would confidently
|
|
135
|
+
* blame a `key` every time React Fast Refresh replaced a module. A real key
|
|
136
|
+
* or inline-definition problem affects one component; a reload affects many
|
|
137
|
+
* at once.
|
|
138
|
+
*/
|
|
139
|
+
private reloadSuspectedAt;
|
|
121
140
|
/** Hot path. Must stay allocation-free and O(1). */
|
|
122
141
|
recordAttempt(node: NodeRecord, props: Record<string, unknown>): void;
|
|
123
142
|
recordStateChange(node: NodeRecord, change: TrackedStateChange): void;
|
|
143
|
+
recordSelectorChange(node: NodeRecord, change: SelectorChange): void;
|
|
124
144
|
/**
|
|
125
145
|
* Hot path. Called from Profiler#onRender; only enqueues.
|
|
126
146
|
*
|
|
@@ -192,10 +212,14 @@ interface DiagnosisInput {
|
|
|
192
212
|
contextChanges: ContextChange[];
|
|
193
213
|
/** Named state updates from `useTrackedState`. Empty unless opted in. */
|
|
194
214
|
trackedState: TrackedStateChange[];
|
|
215
|
+
/** External-store selector values that changed. Empty unless selectors are tracked. */
|
|
216
|
+
selectorChanges: SelectorChange[];
|
|
195
217
|
/** How many times this component has been rebuilt rather than re-rendered. */
|
|
196
218
|
remounts: number;
|
|
197
219
|
/** The component looks like it is declared inside another component's render body. */
|
|
198
220
|
inlineDefinitionSuspected: boolean;
|
|
221
|
+
/** Many components remounted at once — a hot reload or a route change. */
|
|
222
|
+
treeReloadSuspected: boolean;
|
|
199
223
|
selfDuration: number;
|
|
200
224
|
attempts: number;
|
|
201
225
|
committed: boolean;
|
|
@@ -236,4 +260,4 @@ declare class RingBuffer<T> {
|
|
|
236
260
|
resize(capacity: number): void;
|
|
237
261
|
}
|
|
238
262
|
|
|
239
|
-
export { AppStats, ComponentStats, ContextChange, Detective, DetectiveConfig, DetectiveOptions, Diagnosis, type DiagnosisInput, Inspected, InspectionLimits, PropChange, PropValueType, RenderEvent, RenderPhase, RenderReason, RingBuffer, Thresholds, TrackedStateChange, defaultConfig, detectDev, diagnose, diffProps, formatInspected, getDetective, inspect, isPlainObject, isReactElement, matches, mergeConfig, severityFor, shallowEqual, shouldInstrument, valueType };
|
|
263
|
+
export { AppStats, ComponentStats, ContextChange, Detective, DetectiveConfig, DetectiveOptions, Diagnosis, type DiagnosisInput, Inspected, InspectionLimits, PropChange, PropValueType, RenderEvent, RenderPhase, RenderReason, RingBuffer, SelectorChange, Thresholds, TrackedStateChange, defaultConfig, detectDev, diagnose, diffProps, formatInspected, getDetective, inspect, isPlainObject, isReactElement, matches, mergeConfig, severityFor, shallowEqual, shouldInstrument, valueType };
|
package/dist/core.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { Detective, RingBuffer, defaultConfig, detectDev, diagnose, diffProps, formatInspected, getDetective, inspect, isPlainObject, isReactElement, matches, mergeConfig, severityFor, shallowEqual, shouldInstrument, valueType } from './chunk-
|
|
1
|
+
export { Detective, RingBuffer, defaultConfig, detectDev, diagnose, diffProps, formatInspected, getDetective, inspect, isPlainObject, isReactElement, matches, mergeConfig, severityFor, shallowEqual, shouldInstrument, valueType } from './chunk-3TZNM7JO.js';
|
|
2
2
|
//# sourceMappingURL=core.js.map
|
|
3
3
|
//# sourceMappingURL=core.js.map
|