@atlassian/chippy 0.0.0-stage → 0.0.1-beta.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/LICENSE +201 -0
- package/README.md +276 -2
- package/bin/chippy.mjs +92 -0
- package/bin/pack.mjs +204 -0
- package/bin/skill-dir.mjs +15 -0
- package/lib/avalanche.js +2601 -0
- package/lib/avalanche.js.map +7 -0
- package/lib/bootstrap.d.ts +1 -0
- package/lib/bootstrap.js +70 -0
- package/lib/bootstrap.js.map +7 -0
- package/lib/browser.js +15 -0
- package/lib/browser.js.map +7 -0
- package/lib/extension/avalanche.es.js +5535 -0
- package/lib/extension/avalanche.es.js.map +1 -0
- package/lib/extension/chippy-page-bridge.js +1953 -0
- package/lib/extension/inspect-react.js +216 -0
- package/lib/extension/layout-lab.js +1453 -0
- package/lib/extension/panel-dom.js +90 -0
- package/lib/extension/resolve-probes.js +342 -0
- package/lib/mcp-skill/LICENSE +201 -0
- package/lib/mcp-skill/README.md +148 -0
- package/lib/mcp-skill/SKILL.md +335 -0
- package/lib/mcp-skill/browser-scripts/playwright-probes.js +368 -0
- package/lib/mcp-skill/browser-scripts/playwright-session.js +114 -0
- package/lib/mcp-skill/extension/armed-reload-startup.js +83 -0
- package/lib/mcp-skill/extension/avalanche.es.js +5535 -0
- package/lib/mcp-skill/extension/avalanche.es.js.map +1 -0
- package/lib/mcp-skill/extension/avalanche.iife.js +5536 -0
- package/lib/mcp-skill/extension/avalanche.iife.js.map +1 -0
- package/lib/mcp-skill/extension/background.js +325 -0
- package/lib/mcp-skill/extension/chippy-page-bridge.js +1953 -0
- package/lib/mcp-skill/extension/content-script.js +190 -0
- package/lib/mcp-skill/extension/devtools-hook-shim.js +85 -0
- package/lib/mcp-skill/extension/early-bootstrap.js +49 -0
- package/lib/mcp-skill/extension/icon-128.png +0 -0
- package/lib/mcp-skill/extension/icon-16.png +0 -0
- package/lib/mcp-skill/extension/icon-32.png +0 -0
- package/lib/mcp-skill/extension/icon-48.png +0 -0
- package/lib/mcp-skill/extension/inspect-react.js +216 -0
- package/lib/mcp-skill/extension/layout-lab.js +1453 -0
- package/lib/mcp-skill/extension/logo.svg +14 -0
- package/lib/mcp-skill/extension/manifest.json +69 -0
- package/lib/mcp-skill/extension/panel-dom.js +90 -0
- package/lib/mcp-skill/extension/panel-settings.js +173 -0
- package/lib/mcp-skill/extension/popup.html +41 -0
- package/lib/mcp-skill/extension/popup.js +80 -0
- package/lib/mcp-skill/extension/probe-descriptor.js +241 -0
- package/lib/mcp-skill/extension/resolve-probes.js +342 -0
- package/lib/mcp-skill/extension/startup-handoff.js +30 -0
- package/lib/mcp-skill/package.json +1 -0
- package/lib/mcp-skill/references/README.md +56 -0
- package/lib/mcp-skill/references/active-stimulus.md +85 -0
- package/lib/mcp-skill/references/avalanche-detector.md +731 -0
- package/lib/mcp-skill/references/bdd-router.md +310 -0
- package/lib/mcp-skill/references/browser-runtime-api.md +193 -0
- package/lib/mcp-skill/references/command-output-formats.md +1085 -0
- package/lib/mcp-skill/references/command-surface.md +183 -0
- package/lib/mcp-skill/references/cynefin.md +99 -0
- package/lib/mcp-skill/references/debug-hook.md +161 -0
- package/lib/mcp-skill/references/fixing-performance.md +490 -0
- package/lib/mcp-skill/references/hook-metrics.md +199 -0
- package/lib/mcp-skill/references/hooks-inspection.md +61 -0
- package/lib/mcp-skill/references/jira-taxonomy.md +81 -0
- package/lib/mcp-skill/references/mcp.md +122 -0
- package/lib/mcp-skill/references/mode-a-injection.md +102 -0
- package/lib/mcp-skill/references/operating-model.md +128 -0
- package/lib/mcp-skill/references/playwright-cli-setup.md +105 -0
- package/lib/mcp-skill/references/playwright-probes.md +205 -0
- package/lib/mcp-skill/references/procedures.md +545 -0
- package/lib/mcp-skill/references/recipes.txt +114 -0
- package/lib/mcp-skill/references/stability-render.md +428 -0
- package/lib/mcp-skill/references/test-mode-playbook.md +194 -0
- package/lib/mcp-skill/references/troubleshooting.md +59 -0
- package/lib/mcp-skill/scripts/avalanche-analyze.cjs +495 -0
- package/lib/mcp-skill/scripts/build-avalanche-command.js +34 -0
- package/lib/mcp-skill/scripts/build-fiber-state-command.js +19 -0
- package/lib/mcp-skill/scripts/chippy-helper-server.js +1768 -0
- package/lib/mcp-skill/scripts/chippy-mcp.cjs +273 -0
- package/lib/mcp-skill/scripts/chippy.sh +1252 -0
- package/lib/mcp-skill/scripts/format-probe-result.js +34 -0
- package/lib/mcp-skill/scripts/helper-access.js +158 -0
- package/lib/mcp-skill/scripts/helper-proxy.js +87 -0
- package/lib/mcp-skill/scripts/page-socket-trust.js +81 -0
- package/lib/mcp-skill/scripts/probe-annotation-channel.js +116 -0
- package/lib/mcp-skill/scripts/search-recipes.js +248 -0
- package/lib/mcp-skill/snippets/README.md +89 -0
- package/lib/mcp-skill/snippets/count-context-consumers.js +40 -0
- package/lib/mcp-skill/snippets/find-context-providers.js +38 -0
- package/lib/mcp-skill/snippets/find-legacy-context.js +47 -0
- package/lib/mcp-skill/snippets/find-prop.js +83 -0
- package/lib/mcp-skill/snippets/hook-metrics-sample.js +69 -0
- package/lib/mcp-skill/snippets/hook-metrics.js +60 -0
- package/lib/mcp-skill/snippets/hook-tracker.js +198 -0
- package/lib/mcp-skill/snippets/stability-nudge.js +101 -0
- package/lib/package.json +1 -0
- package/lib/plugin.js +119 -0
- package/lib/plugin.js.map +7 -0
- package/lib/storybook/avalanche-panel-model.js +79 -0
- package/lib/storybook/brand.jsx +6 -0
- package/lib/storybook/connection-fallback.jsx +47 -0
- package/lib/storybook/constants.js +15 -0
- package/lib/storybook/context-card.jsx +171 -0
- package/lib/storybook/manager-owner.js +42 -0
- package/lib/storybook/manager.jsx +425 -0
- package/lib/storybook/preset.js +7 -0
- package/lib/storybook/preview.js +298 -0
- package/lib/storybook/probe-annotation-editor.jsx +52 -0
- package/lib/storybook/probe-intent.js +23 -0
- package/lib/storybook/setup.js +104 -0
- package/lib/types/avalanche/commit-metrics-adapter.d.ts +76 -0
- package/lib/types/avalanche/commit-stats-indices.d.ts +41 -0
- package/lib/types/avalanche/commit-surface-ownership.d.ts +9 -0
- package/lib/types/avalanche/detector.d.ts +183 -0
- package/lib/types/avalanche/interaction-capture.d.ts +25 -0
- package/lib/types/avalanche/internals.d.ts +189 -0
- package/lib/types/avalanche/report-serializer.d.ts +283 -0
- package/lib/types/avalanche/reporter.d.ts +610 -0
- package/lib/types/chippy-bridge/fiber-source.d.ts +48 -0
- package/lib/types/chippy-bridge/react-renderer.d.ts +74 -0
- package/lib/types/chippy-bridge/recorded-source.d.ts +44 -0
- package/lib/types/chippy-bridge/source-map.d.ts +30 -0
- package/lib/types/debug-render/core.d.ts +78 -0
- package/lib/types/layout-lab/fiber-boundaries.d.ts +51 -0
- package/lib/types/layout-lab/fiber-walk.d.ts +131 -0
- package/lib/types/layout-lab/marker-context.d.ts +94 -0
- package/lib/types/package/avalanche.d.ts +6 -0
- package/lib/types/package/browser.d.ts +10 -0
- package/lib/types/package/plugin.d.ts +15 -0
- package/lib/types/plugins/atl/commit-metrics-adapter.d.ts +65 -0
- package/lib/types/plugins/atl/metrics-slot.d.ts +37 -0
- package/lib/types/plugins/index.d.ts +49 -0
- package/lib/types/plugins/jira/context-provider.d.ts +36 -0
- package/package.json +106 -4
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared React DevTools renderer discovery.
|
|
3
|
+
*
|
|
4
|
+
* React-DOM registers a renderer object into
|
|
5
|
+
* `window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers` at injection time (only when
|
|
6
|
+
* the hook exists before react-dom evaluates). That renderer object is the single
|
|
7
|
+
* entry point for several Chippy capabilities:
|
|
8
|
+
*
|
|
9
|
+
* - `currentDispatcherRef` → debug-render hook replay (see debug-render/core.ts)
|
|
10
|
+
* - `scheduleUpdate` → fiber-schedule-update nudge (see fiber-schedule-update.ts)
|
|
11
|
+
*
|
|
12
|
+
* Both used to walk `hook.renderers` themselves. This module is the one place that
|
|
13
|
+
* knows how to enumerate renderers, so capabilities select the field they need
|
|
14
|
+
* without duplicating the iteration (and its Map/entries quirks).
|
|
15
|
+
*/
|
|
16
|
+
export type ReactRenderer = {
|
|
17
|
+
/** `{ current }` on React <=18; `ReactSharedInternals` (`H`) on React 19. */
|
|
18
|
+
currentDispatcherRef?: Record<string, unknown> | null;
|
|
19
|
+
scheduleUpdate?: (fiber: unknown) => void;
|
|
20
|
+
version?: string;
|
|
21
|
+
rendererPackageName?: string;
|
|
22
|
+
[key: string]: unknown;
|
|
23
|
+
};
|
|
24
|
+
export type DevtoolsHookLike = {
|
|
25
|
+
renderers?: Map<number, ReactRenderer> | {
|
|
26
|
+
entries(): IterableIterator<[number, ReactRenderer]>;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Enumerate every registered React renderer. Returns [] when the DevTools hook
|
|
31
|
+
* is absent or empty (production builds without the shim, or hook installed too
|
|
32
|
+
* late for react-dom to register).
|
|
33
|
+
*/
|
|
34
|
+
export declare function getReactRenderers(scope?: typeof globalThis): ReactRenderer[];
|
|
35
|
+
/**
|
|
36
|
+
* The writable property that holds React's active hooks dispatcher.
|
|
37
|
+
*
|
|
38
|
+
* React <=18 injects `ReactCurrentDispatcher`, whose dispatcher lives at
|
|
39
|
+
* `current`. React 19 injects `ReactSharedInternals`, whose dispatcher lives
|
|
40
|
+
* at `H` (`current` does not exist there). React DevTools makes the same
|
|
41
|
+
* distinction in its own `getDispatcherRef`.
|
|
42
|
+
*/
|
|
43
|
+
export type DispatcherSlot = {
|
|
44
|
+
owner: Record<string, unknown>;
|
|
45
|
+
key: 'current' | 'H';
|
|
46
|
+
};
|
|
47
|
+
export declare function dispatcherSlotOf(injected: unknown): DispatcherSlot | null;
|
|
48
|
+
/**
|
|
49
|
+
* First renderer that exposes a usable dispatcher slot. Used by debug-render
|
|
50
|
+
* when it must trap writes to the exact property React assigns.
|
|
51
|
+
*/
|
|
52
|
+
export declare function getDispatcherSlot(scope?: typeof globalThis): DispatcherSlot | null;
|
|
53
|
+
/**
|
|
54
|
+
* Normalize a slot to a `{ current }` ref. A legacy ref is returned as-is; a
|
|
55
|
+
* React 19 internals object gets one stable accessor view that reads and
|
|
56
|
+
* writes `H`.
|
|
57
|
+
*/
|
|
58
|
+
export declare function dispatcherRefOf(slot: DispatcherSlot): {
|
|
59
|
+
current: unknown;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* First renderer's hooks dispatcher as a `{ current }` ref, across React
|
|
63
|
+
* versions. Used by debug replay to swap in its stub dispatcher.
|
|
64
|
+
*/
|
|
65
|
+
export declare function getDispatcherRef(scope?: typeof globalThis): {
|
|
66
|
+
current: unknown;
|
|
67
|
+
} | null;
|
|
68
|
+
/**
|
|
69
|
+
* First renderer that exposes a callable `scheduleUpdate`. This is the exact
|
|
70
|
+
* function React DevTools uses to force a re-render on a fiber. It is only
|
|
71
|
+
* present on development React builds. Returns null on production builds (or
|
|
72
|
+
* when the DevTools-hook shim was missing at page boot).
|
|
73
|
+
*/
|
|
74
|
+
export declare function getScheduleUpdate(scope?: typeof globalThis): ((fiber: unknown) => void) | null;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Correct React <=18 `_debugSource` lines through the served module.
|
|
3
|
+
*
|
|
4
|
+
* The JSX transform records `lineNumber`/`columnNumber` from the code it
|
|
5
|
+
* receives. When an earlier transform adds lines first, the recorded position
|
|
6
|
+
* points into that intermediate code rather than the authored file. For
|
|
7
|
+
* example, `@vitejs/plugin-react` adds a Fast Refresh header before esbuild
|
|
8
|
+
* compiles JSX, which shifts every recorded line in the module.
|
|
9
|
+
*
|
|
10
|
+
* The served module still contains the recorded literal, and its source map
|
|
11
|
+
* maps that literal to the JSX element in the authored file. This module finds
|
|
12
|
+
* the literal and the URLs that may serve the recorded file; the call-site
|
|
13
|
+
* resolver in fiber-source.ts fetches the module and applies the map.
|
|
14
|
+
*/
|
|
15
|
+
export type RecordedSource = {
|
|
16
|
+
fileName: string;
|
|
17
|
+
lineNumber: number;
|
|
18
|
+
columnNumber: number | null;
|
|
19
|
+
};
|
|
20
|
+
export type ServedPosition = {
|
|
21
|
+
line: number;
|
|
22
|
+
column: number;
|
|
23
|
+
};
|
|
24
|
+
export type PageModules = {
|
|
25
|
+
origin: string;
|
|
26
|
+
/** Script and module URLs the page loaded, oldest first. */
|
|
27
|
+
resourceUrls: readonly string[];
|
|
28
|
+
/** Vite serves any allowed file from `/@fs/<absolute path>`. */
|
|
29
|
+
vite: boolean;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* The position of the single debug literal for `source` in served code, or
|
|
33
|
+
* null when the literal is missing or appears more than once.
|
|
34
|
+
*/
|
|
35
|
+
export declare function recordedLiteralPosition(code: string, source: RecordedSource): ServedPosition | null;
|
|
36
|
+
/**
|
|
37
|
+
* Same-origin URLs that may serve `fileName`, best match first: loaded modules
|
|
38
|
+
* whose path ends the recorded file path, newest first, then Vite's `/@fs`
|
|
39
|
+
* URL when the page runs on Vite.
|
|
40
|
+
*/
|
|
41
|
+
export declare function servedModuleUrls(fileName: string, page: PageModules): string[];
|
|
42
|
+
/** Candidate module URLs for a recorded file on the current page. */
|
|
43
|
+
export declare function pageModuleUrls(fileName: string): string[];
|
|
44
|
+
export declare function baseName(path: string): string;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Small, dependency-free Source Map v3 reader.
|
|
3
|
+
*
|
|
4
|
+
* Chippy only needs the generated-position lookup used by React 19's
|
|
5
|
+
* `_debugStack` source path, so it deliberately omits names and source contents.
|
|
6
|
+
*/
|
|
7
|
+
type Segment = {
|
|
8
|
+
generatedColumn: number;
|
|
9
|
+
sourceIndex: number | null;
|
|
10
|
+
originalLine: number | null;
|
|
11
|
+
originalColumn: number | null;
|
|
12
|
+
};
|
|
13
|
+
export type SourceMap = {
|
|
14
|
+
sources: readonly string[];
|
|
15
|
+
lines: readonly (readonly Segment[])[];
|
|
16
|
+
offset: {
|
|
17
|
+
line: number;
|
|
18
|
+
column: number;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export type OriginalPosition = {
|
|
22
|
+
source: string;
|
|
23
|
+
line: number;
|
|
24
|
+
column: number;
|
|
25
|
+
};
|
|
26
|
+
export declare function parseSourceMap(text: string): SourceMap[];
|
|
27
|
+
export declare function originalPositionFor(maps: readonly SourceMap[], line: number, column: number): OriginalPosition | null;
|
|
28
|
+
export declare function sourceMappingUrlOf(code: string): string | null;
|
|
29
|
+
export declare function inlineSourceMapOf(url: string): string | null;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug-render module.
|
|
3
|
+
*
|
|
4
|
+
* Single responsibility: capture per-render hook events for components, and
|
|
5
|
+
* expose them losslessly to higher layers (the detector projects them).
|
|
6
|
+
*
|
|
7
|
+
* Capture strategy: dispatcher interception via the DevTools global hook.
|
|
8
|
+
*
|
|
9
|
+
* React 18 routes every hook call through `ReactCurrentDispatcher.current`,
|
|
10
|
+
* which is swapped per render phase by react-dom. We do NOT patch
|
|
11
|
+
* `React.useX` (those are facades to the dispatcher) and we do NOT import
|
|
12
|
+
* React here — this module must not pin a React identity.
|
|
13
|
+
*
|
|
14
|
+
* We discover the *page's* `ReactCurrentDispatcher` ref via the React DevTools
|
|
15
|
+
* global hook contract:
|
|
16
|
+
*
|
|
17
|
+
* __REACT_DEVTOOLS_GLOBAL_HOOK__.renderers.get(id).currentDispatcherRef
|
|
18
|
+
*
|
|
19
|
+
* That ref is page-React-owned and lives where react-dom actually writes.
|
|
20
|
+
* Bootstrap requirement: a DevTools hook shim must already be installed when
|
|
21
|
+
* react-dom evaluates so it calls `hook.inject(internals)`. That bootstrap is
|
|
22
|
+
* Chippy's responsibility (handled by the extension content-script / helper
|
|
23
|
+
* inject path); this module only consumes the result.
|
|
24
|
+
*
|
|
25
|
+
* Capture is intentionally lossless: raw stack + parsed frames are stored.
|
|
26
|
+
* Projection (component name, custom-hook path, loc) is done downstream so
|
|
27
|
+
* the original evidence can be re-projected without re-capturing.
|
|
28
|
+
*/
|
|
29
|
+
export type StackFrame = {
|
|
30
|
+
name: string;
|
|
31
|
+
loc: string;
|
|
32
|
+
};
|
|
33
|
+
export type HookCallEvent = {
|
|
34
|
+
primitive: string;
|
|
35
|
+
stack: string;
|
|
36
|
+
frames: StackFrame[];
|
|
37
|
+
componentName: string;
|
|
38
|
+
args: unknown[];
|
|
39
|
+
};
|
|
40
|
+
export type CaptureEngineStatus = {
|
|
41
|
+
ok: boolean;
|
|
42
|
+
installed: boolean;
|
|
43
|
+
hasDevtoolsHook: boolean;
|
|
44
|
+
rendererCount: number;
|
|
45
|
+
hasDispatcherRef: boolean;
|
|
46
|
+
totalCapturedComponents: number;
|
|
47
|
+
totalCapturedEvents: number;
|
|
48
|
+
reason?: string;
|
|
49
|
+
hint?: string;
|
|
50
|
+
};
|
|
51
|
+
export type DebugRenderModule = {
|
|
52
|
+
install(): {
|
|
53
|
+
ok: boolean;
|
|
54
|
+
reason?: string;
|
|
55
|
+
};
|
|
56
|
+
uninstall(): void;
|
|
57
|
+
reset(): void;
|
|
58
|
+
isInstalled(): boolean;
|
|
59
|
+
dispatcherRef(): DispatcherRef | null;
|
|
60
|
+
rawEvents(componentName: string): HookCallEvent[];
|
|
61
|
+
allComponents(): string[];
|
|
62
|
+
status(): CaptureEngineStatus;
|
|
63
|
+
recordEventForTest?(event: HookCallEvent): void;
|
|
64
|
+
};
|
|
65
|
+
export declare function parseStackFrames(stack: string): StackFrame[];
|
|
66
|
+
type DispatcherRef = {
|
|
67
|
+
current: unknown;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* True for a hook frame, including qualified names. React 19's CommonJS build
|
|
71
|
+
* defines `exports.useState = function (...) {}`, which V8 names
|
|
72
|
+
* `exports.useState`; bundlers can produce similar `ns.useX` names.
|
|
73
|
+
*/
|
|
74
|
+
export declare function isHookFrameName(name: string): boolean;
|
|
75
|
+
export declare function createDebugRender(options?: {
|
|
76
|
+
maxEventsPerComponent?: number;
|
|
77
|
+
}): DebugRenderModule;
|
|
78
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fiber-native declarative boundaries.
|
|
3
|
+
*
|
|
4
|
+
* Error boundaries and Suspense are React primitives — they exist on every
|
|
5
|
+
* React page. This module detects them generically from the fiber tree,
|
|
6
|
+
* independent of any product. App-specific enrichment (ownership markers,
|
|
7
|
+
* error-boundary props) is layered on top by context providers registered
|
|
8
|
+
* with ./marker-context.
|
|
9
|
+
*
|
|
10
|
+
* "Distance" is the signal: how many fiber hops above the probed fiber the
|
|
11
|
+
* boundary sits. Together, the nearest error + suspense boundaries define the
|
|
12
|
+
* collateral scope around a probe.
|
|
13
|
+
*/
|
|
14
|
+
import { type Fiber } from './fiber-walk.js';
|
|
15
|
+
export type ErrorBoundaryInfo = {
|
|
16
|
+
componentName: string;
|
|
17
|
+
/** How the boundary was identified — lifecycle proof vs. name heuristic. */
|
|
18
|
+
detectedBy: 'lifecycle' | 'name';
|
|
19
|
+
};
|
|
20
|
+
export type SuspenseBoundaryInfo = {
|
|
21
|
+
componentName: string;
|
|
22
|
+
};
|
|
23
|
+
/** A boundary plus its fiber-hop distance from the probed fiber. */
|
|
24
|
+
export type BoundaryRef<T> = T & {
|
|
25
|
+
distance: number;
|
|
26
|
+
};
|
|
27
|
+
export type FiberBoundaries = {
|
|
28
|
+
error: BoundaryRef<ErrorBoundaryInfo> | null;
|
|
29
|
+
suspense: BoundaryRef<SuspenseBoundaryInfo> | null;
|
|
30
|
+
};
|
|
31
|
+
export declare const MAX_BOUNDARY_FIBERS = 400;
|
|
32
|
+
/**
|
|
33
|
+
* Generic error-boundary detection. An error boundary is a class component that
|
|
34
|
+
* implements getDerivedStateFromError and/or componentDidCatch. That lifecycle
|
|
35
|
+
* check is the React-native definition and works on any React app. As a
|
|
36
|
+
* fallback for minified/edge builds where the constructor is not introspectable,
|
|
37
|
+
* a display name ending in "ErrorBoundary" is accepted.
|
|
38
|
+
*/
|
|
39
|
+
export declare function describeErrorBoundary(fiber: Fiber): ErrorBoundaryInfo | null;
|
|
40
|
+
/**
|
|
41
|
+
* Generic Suspense detection. React marks a Suspense fiber with tag 13; we also
|
|
42
|
+
* accept a display name resolving to Suspense/SuspenseList for builds where the
|
|
43
|
+
* tag is unavailable.
|
|
44
|
+
*/
|
|
45
|
+
export declare function describeSuspenseBoundary(fiber: Fiber): SuspenseBoundaryInfo | null;
|
|
46
|
+
/**
|
|
47
|
+
* Walk an ordered ancestry list and return the nearest error + suspense
|
|
48
|
+
* boundaries with their distances. The list is expected to be ordered from the
|
|
49
|
+
* probed fiber outward, so the index is the fiber-hop distance.
|
|
50
|
+
*/
|
|
51
|
+
export declare function collectFiberBoundaries(fibers: Fiber[]): FiberBoundaries;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure fiber-walk helpers extracted from layout-lab.js.
|
|
3
|
+
* No DOM writes, no side effects — read-only introspection of React fiber trees.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Minimal duck-typed Fiber shape.
|
|
7
|
+
* Only fields used by these helpers are typed; rest may exist but are not read.
|
|
8
|
+
*/
|
|
9
|
+
export type Fiber = {
|
|
10
|
+
type?: unknown;
|
|
11
|
+
elementType?: unknown;
|
|
12
|
+
key?: string | null;
|
|
13
|
+
memoizedState?: unknown;
|
|
14
|
+
memoizedProps?: Record<string, unknown> | null;
|
|
15
|
+
stateNode?: Element | null;
|
|
16
|
+
return?: Fiber | null;
|
|
17
|
+
child?: Fiber | null;
|
|
18
|
+
sibling?: Fiber | null;
|
|
19
|
+
_debugOwner?: Fiber | null;
|
|
20
|
+
_debugSource?: SourceLocation | null;
|
|
21
|
+
_debugStack?: unknown;
|
|
22
|
+
};
|
|
23
|
+
export type SourceLocation = {
|
|
24
|
+
fileName?: string | null;
|
|
25
|
+
lineNumber?: number | null;
|
|
26
|
+
columnNumber?: number | null;
|
|
27
|
+
};
|
|
28
|
+
export type DescribedSource = {
|
|
29
|
+
fileName: string | null;
|
|
30
|
+
lineNumber: number | null;
|
|
31
|
+
columnNumber: number | null;
|
|
32
|
+
};
|
|
33
|
+
export type HookSummary = {
|
|
34
|
+
hookCount: number;
|
|
35
|
+
hookCountTruncated: boolean;
|
|
36
|
+
hookCountMax: number;
|
|
37
|
+
};
|
|
38
|
+
export type OwnerEntry = {
|
|
39
|
+
name: string | null;
|
|
40
|
+
key: string | null;
|
|
41
|
+
props: string[];
|
|
42
|
+
} & HookSummary & {
|
|
43
|
+
source: DescribedSource | null;
|
|
44
|
+
};
|
|
45
|
+
export type FiberTarget = {
|
|
46
|
+
domTag: string | null;
|
|
47
|
+
domText: string;
|
|
48
|
+
fiberType: string | null;
|
|
49
|
+
source: DescribedSource | null;
|
|
50
|
+
};
|
|
51
|
+
export type ComponentDescription = {
|
|
52
|
+
name: string | null;
|
|
53
|
+
key: string | null;
|
|
54
|
+
props: Record<string, unknown>;
|
|
55
|
+
source: DescribedSource | null;
|
|
56
|
+
stateNode: string | null;
|
|
57
|
+
owners: OwnerEntry[];
|
|
58
|
+
parents: OwnerEntry[];
|
|
59
|
+
} & HookSummary;
|
|
60
|
+
/**
|
|
61
|
+
* Find the React fiber key in a DOM node's own properties.
|
|
62
|
+
* Returns the property name (e.g. '__reactFiber$abc123') or null.
|
|
63
|
+
*/
|
|
64
|
+
export declare function getFiberKey(node: Node | Element | null | undefined): string | null;
|
|
65
|
+
/**
|
|
66
|
+
* Get the React fiber attached to a DOM node, or null if not a React host node.
|
|
67
|
+
*/
|
|
68
|
+
export declare function getFiber(node: Node | Element | null | undefined): Fiber | null;
|
|
69
|
+
/**
|
|
70
|
+
* Extract display name from a React type (class, function, or string).
|
|
71
|
+
* Returns displayName > name > null for functions; 'string' for primitives.
|
|
72
|
+
*/
|
|
73
|
+
export declare function getDisplayName(type: unknown): string | null;
|
|
74
|
+
/**
|
|
75
|
+
* True if fiber is a user-defined component (not a DOM string, not a hook-internal wrapper).
|
|
76
|
+
*/
|
|
77
|
+
export declare function isUserComponent(fiber: Fiber | null | undefined): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Walk DOM parents to find the nearest fiber-attached element.
|
|
80
|
+
*/
|
|
81
|
+
export declare function getNearestFiber(domNode: Node | Element | null | undefined): Fiber | null;
|
|
82
|
+
/**
|
|
83
|
+
* Walk DOM parents, then walk fiber return chain, to find the nearest user component.
|
|
84
|
+
*/
|
|
85
|
+
export declare function getNearestComponent(domNode: Node | Element | null | undefined): Fiber | null;
|
|
86
|
+
/**
|
|
87
|
+
* Count hooks in fiber.memoizedState linked list; detect cycle.
|
|
88
|
+
*/
|
|
89
|
+
export declare function getHookSummary(fiber: Fiber | null | undefined): HookSummary;
|
|
90
|
+
/**
|
|
91
|
+
* Walk fiber._debugOwner chain; collect all user components with metadata.
|
|
92
|
+
* Returns empty array if fiber or owner chain is null.
|
|
93
|
+
*/
|
|
94
|
+
export declare function getOwnerChain(fiber: Fiber | null | undefined): OwnerEntry[];
|
|
95
|
+
/**
|
|
96
|
+
* Walk fiber._debugOwner chain; return raw fiber nodes (for navigation).
|
|
97
|
+
*/
|
|
98
|
+
export declare function getOwnerFibers(fiber: Fiber | null | undefined): Fiber[];
|
|
99
|
+
/**
|
|
100
|
+
* Recursively walk fiber.child/sibling to find the first host DOM element rendered by this subtree.
|
|
101
|
+
*/
|
|
102
|
+
export declare function getFiberDomNode(fiber: Fiber | null | undefined): Element | null;
|
|
103
|
+
/**
|
|
104
|
+
* Walk fiber.return chain; collect all user component parents with metadata.
|
|
105
|
+
*/
|
|
106
|
+
export declare function getReturnComponentChain(fiber: Fiber | null | undefined): OwnerEntry[];
|
|
107
|
+
/**
|
|
108
|
+
* Walk fiber.return chain; return raw fiber nodes (for navigation).
|
|
109
|
+
*/
|
|
110
|
+
export declare function getReturnComponentFibers(fiber: Fiber | null | undefined): Fiber[];
|
|
111
|
+
/**
|
|
112
|
+
* Normalize source location object to canonical shape.
|
|
113
|
+
*/
|
|
114
|
+
export declare function describeSource(source: SourceLocation | null | undefined): DescribedSource | null;
|
|
115
|
+
/**
|
|
116
|
+
* Read a fiber source across React versions.
|
|
117
|
+
*
|
|
118
|
+
* React <=18 exposes `_debugSource`. React 19 exposes `_debugStack`; its first
|
|
119
|
+
* non-vendor frame is returned synchronously and may later be upgraded from the
|
|
120
|
+
* bundle position to the original source position by `resolveFiberSource`.
|
|
121
|
+
*/
|
|
122
|
+
export declare function describeFiberSource(fiber: Fiber | null | undefined): DescribedSource | null;
|
|
123
|
+
export declare function resolveFiberSource(fiber: Fiber | null | undefined): Promise<DescribedSource | null>;
|
|
124
|
+
/**
|
|
125
|
+
* Describe a fiber + DOM node pair; used for inspection UI.
|
|
126
|
+
*/
|
|
127
|
+
export declare function describeFiberTarget(fiber: Fiber | null | undefined, domNode: Element | null | undefined): FiberTarget | null;
|
|
128
|
+
/**
|
|
129
|
+
* Full component description: name, props, hook summary, source, owners, parents.
|
|
130
|
+
*/
|
|
131
|
+
export declare function describeComponent(fiber: Fiber | null | undefined): ComponentDescription | null;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product-neutral marker context: the declarative boundaries around a probed
|
|
3
|
+
* fiber, plus whatever registered context providers add on top.
|
|
4
|
+
*
|
|
5
|
+
* The core detects Error and Suspense boundaries from fiber-native signals
|
|
6
|
+
* (./fiber-boundaries). A context provider is a plugin that recognizes
|
|
7
|
+
* app-specific conventions (for example an ownership marker component) and
|
|
8
|
+
* contributes named boundary kinds, error-boundary enrichment, and display
|
|
9
|
+
* hints. Providers never become a prerequisite for inspection: with none
|
|
10
|
+
* registered, a context still reports Error and Suspense boundaries.
|
|
11
|
+
*/
|
|
12
|
+
import type { Fiber } from './fiber-walk.js';
|
|
13
|
+
import { type BoundaryRef, type ErrorBoundaryInfo, type SuspenseBoundaryInfo } from './fiber-boundaries.js';
|
|
14
|
+
/** A boundary kind a provider adds next to the core `error` and `suspense`. */
|
|
15
|
+
export type ContextBoundaryKind = {
|
|
16
|
+
kind: string;
|
|
17
|
+
/** Short lozenge label shown in the probe UI, e.g. `owner`. */
|
|
18
|
+
label: string;
|
|
19
|
+
/** CSS color for the lozenge; UIs fall back to a neutral color. */
|
|
20
|
+
accent?: string;
|
|
21
|
+
};
|
|
22
|
+
export type ContextField = {
|
|
23
|
+
label: string;
|
|
24
|
+
value: string;
|
|
25
|
+
};
|
|
26
|
+
/** What one provider found for one probed fiber. Every part is optional. */
|
|
27
|
+
export type ContextContribution = {
|
|
28
|
+
/** Boundaries of this provider's declared kinds; `null` records "looked, not found". */
|
|
29
|
+
boundaries?: Record<string, BoundaryRef<Record<string, unknown>> | null>;
|
|
30
|
+
/** Fields merged onto the generic error boundary when one was found. */
|
|
31
|
+
errorEnrichment?: Record<string, unknown> | null;
|
|
32
|
+
/** Display title per boundary kind (core or provider kind). */
|
|
33
|
+
titles?: Record<string, string>;
|
|
34
|
+
/** Display fields per boundary kind (core or provider kind). */
|
|
35
|
+
fields?: Record<string, ContextField[]>;
|
|
36
|
+
/** Show the error row even when no error boundary fiber was found. */
|
|
37
|
+
showError?: boolean;
|
|
38
|
+
/** Extra top-level fields on the context, kept for provider-specific consumers. */
|
|
39
|
+
extra?: Record<string, unknown>;
|
|
40
|
+
};
|
|
41
|
+
export type ContextProvider = {
|
|
42
|
+
id: string;
|
|
43
|
+
kinds?: ContextBoundaryKind[];
|
|
44
|
+
/** Inspect the probed fiber's ancestry (nearest first). */
|
|
45
|
+
describe(fibers: Fiber[]): ContextContribution | null;
|
|
46
|
+
/** Return the provider kind this fiber is a boundary of, or null. Used for DOM highlighting. */
|
|
47
|
+
matchBoundary?(fiber: Fiber): string | null;
|
|
48
|
+
};
|
|
49
|
+
export type ContextDisplay = {
|
|
50
|
+
/** Provider kinds that have a boundary on this context, in registration order. */
|
|
51
|
+
kinds: ContextBoundaryKind[];
|
|
52
|
+
titles: Record<string, string>;
|
|
53
|
+
fields: Record<string, ContextField[]>;
|
|
54
|
+
showError: boolean;
|
|
55
|
+
};
|
|
56
|
+
export type MarkerContext = {
|
|
57
|
+
boundaries: {
|
|
58
|
+
error: BoundaryRef<ErrorBoundaryInfo & Record<string, unknown>> | null;
|
|
59
|
+
suspense: BoundaryRef<SuspenseBoundaryInfo> | null;
|
|
60
|
+
[kind: string]: BoundaryRef<Record<string, unknown>> | null;
|
|
61
|
+
};
|
|
62
|
+
display: ContextDisplay;
|
|
63
|
+
/** Ids of the providers that contributed to this context. */
|
|
64
|
+
providers: string[];
|
|
65
|
+
[extra: string]: unknown;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Register a context provider. Registering an id again replaces the earlier
|
|
69
|
+
* provider, so a re-injected bundle cannot double-count. Returns an unregister
|
|
70
|
+
* function.
|
|
71
|
+
*/
|
|
72
|
+
export declare function registerContextProvider(provider: ContextProvider): () => void;
|
|
73
|
+
export declare function getContextProviders(): Array<{
|
|
74
|
+
id: string;
|
|
75
|
+
kinds: ContextBoundaryKind[];
|
|
76
|
+
}>;
|
|
77
|
+
/**
|
|
78
|
+
* Collect the selected fiber first, then its rendered parent path, then its
|
|
79
|
+
* debug-owner path. Production builds often lack `_debugOwner`, while
|
|
80
|
+
* development builds benefit from both signals.
|
|
81
|
+
*/
|
|
82
|
+
export declare function collectContextFibers(fiber: Fiber | null | undefined): Fiber[];
|
|
83
|
+
/**
|
|
84
|
+
* Describe the boundaries around a probed fiber. Returns null when neither the
|
|
85
|
+
* core nor any provider found anything, so non-matching trees pay only one
|
|
86
|
+
* bounded ancestry walk.
|
|
87
|
+
*/
|
|
88
|
+
export declare function describeContext(fiber: Fiber | null | undefined): MarkerContext | null;
|
|
89
|
+
/**
|
|
90
|
+
* Locate the actual boundary FIBERS (not serialized descriptors) for every
|
|
91
|
+
* known kind around a probed fiber. Used in-page to resolve a boundary's DOM
|
|
92
|
+
* node for highlighting; it is not part of the serialized snapshot.
|
|
93
|
+
*/
|
|
94
|
+
export declare function findBoundaryFibers(fiber: Fiber | null | undefined): Record<string, Fiber | null>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Standalone commit detector. Install the bootstrap before React DOM loads. */
|
|
2
|
+
export { createAvalancheDetector, DETECTION_LEVEL } from '../avalanche/detector.js';
|
|
3
|
+
export type { DetectorOptions, Report, ReportOptions, SortBy } from '../avalanche/reporter.js';
|
|
4
|
+
export { type CommitMetricsAdapter, type IntegrationMode, registerCommitMetricsAdapter, } from '../avalanche/commit-metrics-adapter.js';
|
|
5
|
+
/** Opt-in adapter for hosts whose react-dom writes `__ATL_REACT_METRICS`. */
|
|
6
|
+
export { atlCommitMetricsAdapter, createATLCommitMetricsAdapter, } from '../plugins/atl/commit-metrics-adapter.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface BrowserConnection {
|
|
2
|
+
chippy: unknown;
|
|
3
|
+
avalanche: unknown;
|
|
4
|
+
connState: string | null;
|
|
5
|
+
integration: unknown;
|
|
6
|
+
activated: boolean | null;
|
|
7
|
+
probesActive: boolean | null;
|
|
8
|
+
}
|
|
9
|
+
/** Connect this document through a running Chippy helper. Reconnect after navigation. */
|
|
10
|
+
export declare function connectChippy(helperUrl?: string): Promise<BrowserConnection>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types and helpers for writing a Chippy plugin. `chippy pack` bundles a
|
|
3
|
+
* plugin module's default export into a custom skill and extension build.
|
|
4
|
+
*/
|
|
5
|
+
import type { ChippyPlugin } from '../plugins/index.js';
|
|
6
|
+
export type { ChippyPlugin, PluginStatus } from '../plugins/index.js';
|
|
7
|
+
export type { ContextBoundaryKind, ContextContribution, ContextField, ContextProvider, } from '../layout-lab/marker-context.js';
|
|
8
|
+
export type { Fiber } from '../layout-lab/fiber-walk.js';
|
|
9
|
+
export type { CommitMetricsAdapter, CommitMetricsDelta, CommitMetricsMeasurement, CommitMetricsRoot, CommitMetricsSnapshot, } from '../avalanche/commit-metrics-adapter.js';
|
|
10
|
+
/** Display name of a fiber's `type`: function, class, memo, or forwardRef. */
|
|
11
|
+
export { getDisplayName } from '../layout-lab/fiber-walk.js';
|
|
12
|
+
/** Fiber name helpers that commit metrics adapters use for hook ancestry. */
|
|
13
|
+
export { getComponentName, isComponentFiber } from '../avalanche/internals.js';
|
|
14
|
+
/** Identity helper that type-checks a plugin definition. */
|
|
15
|
+
export declare function definePlugin(plugin: ChippyPlugin): ChippyPlugin;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ATL commit metrics adapter: reads the render counters that Atlassian's
|
|
3
|
+
* patched react-dom writes into `__ATL_REACT_METRICS` and routes that slot's
|
|
4
|
+
* `onCommitFiberRoot` callback to the detector.
|
|
5
|
+
*
|
|
6
|
+
* The slot name is configurable, so a renamed slot needs no core change.
|
|
7
|
+
*/
|
|
8
|
+
import type { CommitMetricsAdapter, CommitMetricsSnapshot } from '../../avalanche/commit-metrics-adapter.js';
|
|
9
|
+
/**
|
|
10
|
+
* Per-commit ATL delta - work done in a single commit.
|
|
11
|
+
* Enables full reconciliation: ATL work counts ↔ Avalanche component counts.
|
|
12
|
+
*
|
|
13
|
+
* Key relationship (should hold for any commit):
|
|
14
|
+
* componentRenderWithHooksCount + finishClassComponentCount === collateral + sources
|
|
15
|
+
*/
|
|
16
|
+
export type ATLCommitDelta = {
|
|
17
|
+
/** Function components mounted this commit (should be 0 during pure updates!) */
|
|
18
|
+
mountWorkCount: number;
|
|
19
|
+
/** Fiber update work this commit */
|
|
20
|
+
updateWorkCount: number;
|
|
21
|
+
/** Work that reached commit phase */
|
|
22
|
+
commitWorkCount: number;
|
|
23
|
+
performedWorkCount: number;
|
|
24
|
+
/** Work interrupted (priority change) */
|
|
25
|
+
interruptedWorkCount: number;
|
|
26
|
+
/** Component fiber work (class + function) */
|
|
27
|
+
componentWorkCount: number;
|
|
28
|
+
/** Components mounted (should be 0 during pure updates!) */
|
|
29
|
+
componentMountWorkCount: number;
|
|
30
|
+
/** Components updated */
|
|
31
|
+
componentUpdateWorkCount: number;
|
|
32
|
+
/** DOM work (host fibers) */
|
|
33
|
+
domWorkCount: number;
|
|
34
|
+
ticksCount: number;
|
|
35
|
+
/** Context propagation waves */
|
|
36
|
+
contextUpdateCount: number;
|
|
37
|
+
/** Legacy context propagations (tech debt indicator) */
|
|
38
|
+
legacyContextUpdateCount: number;
|
|
39
|
+
/** ALL function components rendered (including hookless) */
|
|
40
|
+
componentRenderWithHooksCount: number;
|
|
41
|
+
/** Class components rendered */
|
|
42
|
+
finishClassComponentCount: number;
|
|
43
|
+
/** useSES-triggered restarts (store mutation detected after concurrent render) */
|
|
44
|
+
externalStoreRestartCount?: number;
|
|
45
|
+
/** Work abandoned due to priority preemption (fibers unwound in prepareFreshStack) */
|
|
46
|
+
priorityInterruptedWorkCount?: number;
|
|
47
|
+
/** Number of sync renderRoot passes in this commit window */
|
|
48
|
+
renderRootSyncCount?: number;
|
|
49
|
+
/** Number of concurrent renderRoot passes in this commit window */
|
|
50
|
+
renderRootConcurrentCount?: number;
|
|
51
|
+
/** useState/useReducer dispatches during this commit (react-dom patch; optional) */
|
|
52
|
+
setStateCount?: number;
|
|
53
|
+
};
|
|
54
|
+
export declare const ATL_DISPATCHER_FRAME = "atlDispatcherHook";
|
|
55
|
+
/** Counter delta between two ATL snapshots. */
|
|
56
|
+
export declare function calculateATLDelta(before: CommitMetricsSnapshot, after: CommitMetricsSnapshot): ATLCommitDelta;
|
|
57
|
+
export type ATLCommitMetricsAdapterOptions = {
|
|
58
|
+
/** Global slot the patched react-dom writes. Default `__ATL_REACT_METRICS`. */
|
|
59
|
+
slotName?: string;
|
|
60
|
+
/** Object that holds the slot. Default `globalThis`. */
|
|
61
|
+
target?: Record<string, unknown>;
|
|
62
|
+
};
|
|
63
|
+
export declare function createATLCommitMetricsAdapter(options?: ATLCommitMetricsAdapterOptions): CommitMetricsAdapter;
|
|
64
|
+
/** The adapter the shipped bundle registers. */
|
|
65
|
+
export declare const atlCommitMetricsAdapter: CommitMetricsAdapter;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seed, protect, and guard a host metrics slot such as `__ATL_REACT_METRICS`.
|
|
3
|
+
*
|
|
4
|
+
* The host page owns the slot. Its instrumented react-dom reads the slot before
|
|
5
|
+
* it calls `onCommitFiberRoot`, and its runtime may zero-fill or delete the slot
|
|
6
|
+
* during hydration cleanup. These helpers never lock the slot: every descriptor
|
|
7
|
+
* they write stays `configurable: true`, and a slot the host already locked is
|
|
8
|
+
* left alone.
|
|
9
|
+
*/
|
|
10
|
+
export declare const DEFAULT_METRICS_SLOT = "__ATL_REACT_METRICS";
|
|
11
|
+
/** Counters a zeroed slot starts with. */
|
|
12
|
+
export declare const METRICS_COUNTER_KEYS: readonly ["mountWorkCount", "updateWorkCount", "commitWorkCount", "interruptedWorkCount", "priorityInterruptedWorkCount", "externalStoreRestartCount", "renderRootSyncCount", "renderRootConcurrentCount", "componentWorkCount", "componentMountWorkCount", "componentUpdateWorkCount", "componentRenderWithHooksCount", "finishClassComponentCount", "domWorkCount", "totalTickCount", "totalCommitCount", "contextUpdateCount", "legacyContextUpdateCount"];
|
|
13
|
+
type SlotTarget = Record<string, unknown>;
|
|
14
|
+
export type MetricsSlotValue = Record<string, unknown>;
|
|
15
|
+
export declare function createZeroMetrics(): MetricsSlotValue;
|
|
16
|
+
/** True when the host owns the slot: non-configurable, or an accessor. */
|
|
17
|
+
export declare function isSlotHostLocked(target: SlotTarget, slotName?: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Write `metrics` as a plain, deletable data property. Honors a host lock
|
|
20
|
+
* (configurable: false). Falls back to plain assignment.
|
|
21
|
+
*/
|
|
22
|
+
export declare function protectMetricsSlot(target: SlotTarget, metrics: MetricsSlotValue, slotName?: string): void;
|
|
23
|
+
/** Seed a fresh zeroed slot. Returns the new metrics object. */
|
|
24
|
+
export declare function seedMetricsSlot(target: SlotTarget, slotName?: string): MetricsSlotValue;
|
|
25
|
+
/**
|
|
26
|
+
* Install a configurable accessor on the slot before React evaluates.
|
|
27
|
+
*
|
|
28
|
+
* - `configurable: true`, so a host `delete` succeeds without a TypeError.
|
|
29
|
+
* After a delete the slot is gone until the next detector install re-seeds it.
|
|
30
|
+
* - `set()` ignores null, undefined, and all-zero writes, so host hydration
|
|
31
|
+
* cleanup that zero-fills the slot cannot orphan the live metrics object.
|
|
32
|
+
* - A slot the host already locked is left alone.
|
|
33
|
+
*
|
|
34
|
+
* Returns true when the accessor was installed.
|
|
35
|
+
*/
|
|
36
|
+
export declare function installMetricsAccessor(target: SlotTarget, slotName?: string): boolean;
|
|
37
|
+
export {};
|