@memlab/mcp-server 2.18.1 → 2.52.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/README.md +8 -14
- package/bin/.eslintrc.js +26 -0
- package/bin/memlab-cli.js +313 -0
- package/dist/artifact-classes.d.ts +86 -0
- package/dist/artifact-classes.d.ts.map +1 -0
- package/dist/artifact-classes.js +261 -0
- package/dist/artifact-classes.js.map +1 -0
- package/dist/capture-mode.d.ts +60 -0
- package/dist/capture-mode.d.ts.map +1 -0
- package/dist/capture-mode.js +39 -0
- package/dist/capture-mode.js.map +1 -0
- package/dist/guardrail.d.ts.map +1 -1
- package/dist/guardrail.js +13 -0
- package/dist/guardrail.js.map +1 -1
- package/dist/heap-state.d.ts +89 -2
- package/dist/heap-state.d.ts.map +1 -1
- package/dist/heap-state.js +186 -2
- package/dist/heap-state.js.map +1 -1
- package/dist/index.js +39 -1
- package/dist/index.js.map +1 -1
- package/dist/progress.d.ts +25 -0
- package/dist/progress.d.ts.map +1 -0
- package/dist/progress.js +46 -0
- package/dist/progress.js.map +1 -0
- package/dist/result-handles.d.ts +11 -0
- package/dist/result-handles.d.ts.map +1 -0
- package/dist/result-handles.js +77 -0
- package/dist/result-handles.js.map +1 -0
- package/dist/string-index.d.ts +55 -0
- package/dist/string-index.d.ts.map +1 -0
- package/dist/string-index.js +91 -0
- package/dist/string-index.js.map +1 -0
- package/dist/tool-registry.d.ts +42 -0
- package/dist/tool-registry.d.ts.map +1 -0
- package/dist/tool-registry.js +20 -0
- package/dist/tool-registry.js.map +1 -0
- package/dist/tools/analyze-run.d.ts +12 -0
- package/dist/tools/analyze-run.d.ts.map +1 -0
- package/dist/tools/analyze-run.js +343 -0
- package/dist/tools/analyze-run.js.map +1 -0
- package/dist/tools/app-heap.d.ts +12 -0
- package/dist/tools/app-heap.d.ts.map +1 -0
- package/dist/tools/app-heap.js +140 -0
- package/dist/tools/app-heap.js.map +1 -0
- package/dist/tools/batch.d.ts +12 -0
- package/dist/tools/batch.d.ts.map +1 -0
- package/dist/tools/batch.js +168 -0
- package/dist/tools/batch.js.map +1 -0
- package/dist/tools/cache-analysis.d.ts.map +1 -1
- package/dist/tools/cache-analysis.js +156 -5
- package/dist/tools/cache-analysis.js.map +1 -1
- package/dist/tools/class-histogram.d.ts.map +1 -1
- package/dist/tools/class-histogram.js +14 -3
- package/dist/tools/class-histogram.js.map +1 -1
- package/dist/tools/collection-trend.d.ts +55 -0
- package/dist/tools/collection-trend.d.ts.map +1 -0
- package/dist/tools/collection-trend.js +315 -0
- package/dist/tools/collection-trend.js.map +1 -0
- package/dist/tools/detached-dom.d.ts +2 -0
- package/dist/tools/detached-dom.d.ts.map +1 -1
- package/dist/tools/detached-dom.js +291 -20
- package/dist/tools/detached-dom.js.map +1 -1
- package/dist/tools/dev-artifacts.d.ts +62 -6
- package/dist/tools/dev-artifacts.d.ts.map +1 -1
- package/dist/tools/dev-artifacts.js +466 -23
- package/dist/tools/dev-artifacts.js.map +1 -1
- package/dist/tools/dominator-attribution.d.ts +12 -0
- package/dist/tools/dominator-attribution.d.ts.map +1 -0
- package/dist/tools/dominator-attribution.js +189 -0
- package/dist/tools/dominator-attribution.js.map +1 -0
- package/dist/tools/dominator-chain.d.ts +12 -0
- package/dist/tools/dominator-chain.d.ts.map +1 -0
- package/dist/tools/dominator-chain.js +92 -0
- package/dist/tools/dominator-chain.js.map +1 -0
- package/dist/tools/duplicate-objects.d.ts +12 -0
- package/dist/tools/duplicate-objects.d.ts.map +1 -0
- package/dist/tools/duplicate-objects.js +172 -0
- package/dist/tools/duplicate-objects.js.map +1 -0
- package/dist/tools/duplicated-strings.d.ts.map +1 -1
- package/dist/tools/duplicated-strings.js +46 -38
- package/dist/tools/duplicated-strings.js.map +1 -1
- package/dist/tools/eval.d.ts +1 -0
- package/dist/tools/eval.d.ts.map +1 -1
- package/dist/tools/eval.js +785 -28
- package/dist/tools/eval.js.map +1 -1
- package/dist/tools/explain-delta.d.ts +12 -0
- package/dist/tools/explain-delta.d.ts.map +1 -0
- package/dist/tools/explain-delta.js +170 -0
- package/dist/tools/explain-delta.js.map +1 -0
- package/dist/tools/find-nodes-by-class.d.ts.map +1 -1
- package/dist/tools/find-nodes-by-class.js +112 -13
- package/dist/tools/find-nodes-by-class.js.map +1 -1
- package/dist/tools/finding-index.d.ts +22 -0
- package/dist/tools/finding-index.d.ts.map +1 -0
- package/dist/tools/finding-index.js +247 -0
- package/dist/tools/finding-index.js.map +1 -0
- package/dist/tools/for-each.d.ts.map +1 -1
- package/dist/tools/for-each.js +15 -3
- package/dist/tools/for-each.js.map +1 -1
- package/dist/tools/get-referrers.d.ts.map +1 -1
- package/dist/tools/get-referrers.js +17 -0
- package/dist/tools/get-referrers.js.map +1 -1
- package/dist/tools/hunt-report.d.ts +12 -0
- package/dist/tools/hunt-report.d.ts.map +1 -0
- package/dist/tools/hunt-report.js +186 -0
- package/dist/tools/hunt-report.js.map +1 -0
- package/dist/tools/hypothesis.d.ts +12 -0
- package/dist/tools/hypothesis.d.ts.map +1 -0
- package/dist/tools/hypothesis.js +221 -0
- package/dist/tools/hypothesis.js.map +1 -0
- package/dist/tools/intern-opportunities.d.ts.map +1 -1
- package/dist/tools/intern-opportunities.js +112 -47
- package/dist/tools/intern-opportunities.js.map +1 -1
- package/dist/tools/ladder.d.ts +33 -0
- package/dist/tools/ladder.d.ts.map +1 -0
- package/dist/tools/ladder.js +266 -0
- package/dist/tools/ladder.js.map +1 -0
- package/dist/tools/largest-objects.d.ts.map +1 -1
- package/dist/tools/largest-objects.js +6 -2
- package/dist/tools/largest-objects.js.map +1 -1
- package/dist/tools/leak-report.d.ts +12 -0
- package/dist/tools/leak-report.d.ts.map +1 -0
- package/dist/tools/leak-report.js +256 -0
- package/dist/tools/leak-report.js.map +1 -0
- package/dist/tools/load-snapshot.d.ts +18 -0
- package/dist/tools/load-snapshot.d.ts.map +1 -1
- package/dist/tools/load-snapshot.js +211 -13
- package/dist/tools/load-snapshot.js.map +1 -1
- package/dist/tools/map-entries.d.ts +12 -0
- package/dist/tools/map-entries.d.ts.map +1 -0
- package/dist/tools/map-entries.js +139 -0
- package/dist/tools/map-entries.js.map +1 -0
- package/dist/tools/match-object.d.ts +12 -0
- package/dist/tools/match-object.d.ts.map +1 -0
- package/dist/tools/match-object.js +165 -0
- package/dist/tools/match-object.js.map +1 -0
- package/dist/tools/object-shape.d.ts.map +1 -1
- package/dist/tools/object-shape.js +53 -5
- package/dist/tools/object-shape.js.map +1 -1
- package/dist/tools/population-diff.d.ts +57 -0
- package/dist/tools/population-diff.d.ts.map +1 -0
- package/dist/tools/population-diff.js +338 -0
- package/dist/tools/population-diff.js.map +1 -0
- package/dist/tools/retainer-layers.d.ts +23 -0
- package/dist/tools/retainer-layers.d.ts.map +1 -0
- package/dist/tools/retainer-layers.js +179 -0
- package/dist/tools/retainer-layers.js.map +1 -0
- package/dist/tools/retainer-summary.d.ts +1 -0
- package/dist/tools/retainer-summary.d.ts.map +1 -1
- package/dist/tools/retainer-summary.js +128 -32
- package/dist/tools/retainer-summary.js.map +1 -1
- package/dist/tools/retainer-trace.d.ts.map +1 -1
- package/dist/tools/retainer-trace.js +4 -2
- package/dist/tools/retainer-trace.js.map +1 -1
- package/dist/tools/search-nodes.d.ts.map +1 -1
- package/dist/tools/search-nodes.js +5 -1
- package/dist/tools/search-nodes.js.map +1 -1
- package/dist/tools/search-strings.d.ts.map +1 -1
- package/dist/tools/search-strings.js +53 -7
- package/dist/tools/search-strings.js.map +1 -1
- package/dist/tools/sequence-analysis.d.ts +49 -0
- package/dist/tools/sequence-analysis.d.ts.map +1 -1
- package/dist/tools/sequence-analysis.js +266 -86
- package/dist/tools/sequence-analysis.js.map +1 -1
- package/dist/tools/shape-histogram.d.ts.map +1 -1
- package/dist/tools/shape-histogram.js +9 -2
- package/dist/tools/shape-histogram.js.map +1 -1
- package/dist/tools/string-patterns.d.ts.map +1 -1
- package/dist/tools/string-patterns.js +5 -4
- package/dist/tools/string-patterns.js.map +1 -1
- package/dist/tools/tools-index.d.ts +12 -0
- package/dist/tools/tools-index.d.ts.map +1 -0
- package/dist/tools/tools-index.js +342 -0
- package/dist/tools/tools-index.js.map +1 -0
- package/dist/tools/verify-fix.d.ts +23 -0
- package/dist/tools/verify-fix.d.ts.map +1 -0
- package/dist/tools/verify-fix.js +211 -0
- package/dist/tools/verify-fix.js.map +1 -0
- package/dist/tools/weakmap-entries.d.ts.map +1 -1
- package/dist/tools/weakmap-entries.js +6 -1
- package/dist/tools/weakmap-entries.js.map +1 -1
- package/dist/utils.d.ts +146 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +335 -10
- package/dist/utils.js.map +1 -1
- package/package.json +5 -4
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @format
|
|
8
|
+
* @oncall memory_lab
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* V8 internal structures emitted while JIT-compiling and warming up code paths.
|
|
12
|
+
* Exercising NEW interactions during a hunt compiles new functions, so this
|
|
13
|
+
* whole family climbs "every step" without being an app leak.
|
|
14
|
+
*
|
|
15
|
+
* Note what is deliberately NOT here: `PropertyArray`, `DescriptorArray`,
|
|
16
|
+
* `(object elements)`, `(object properties)`, `Context`. Those grow with real
|
|
17
|
+
* application objects and suppressing them would hide genuine leaks.
|
|
18
|
+
*/
|
|
19
|
+
const WARMUP_CLASS_NAMES = new Set([
|
|
20
|
+
'InstructionStream',
|
|
21
|
+
'Code',
|
|
22
|
+
'CodeDataContainer',
|
|
23
|
+
'CodeWrapper',
|
|
24
|
+
'BytecodeArray',
|
|
25
|
+
'BytecodeWrapper',
|
|
26
|
+
'FeedbackVector',
|
|
27
|
+
'FeedbackMetadata',
|
|
28
|
+
'FeedbackCell',
|
|
29
|
+
'ClosureFeedbackCellArray',
|
|
30
|
+
'ScopeInfo',
|
|
31
|
+
'SharedFunctionInfo',
|
|
32
|
+
'SharedFunctionInfoWrapper',
|
|
33
|
+
'UncompiledDataWithoutPreparseData',
|
|
34
|
+
'UncompiledDataWithPreparseData',
|
|
35
|
+
'InterpreterData',
|
|
36
|
+
'TrustedByteArray',
|
|
37
|
+
'ProtectedFixedArray',
|
|
38
|
+
'TrustedWeakFixedArray',
|
|
39
|
+
'WeakArrayList',
|
|
40
|
+
'LoadHandler',
|
|
41
|
+
'StoreHandler',
|
|
42
|
+
'AllocationSite',
|
|
43
|
+
'ConstantPool',
|
|
44
|
+
'(constant pool)',
|
|
45
|
+
'ObjectBoilerplateDescription',
|
|
46
|
+
]);
|
|
47
|
+
/**
|
|
48
|
+
* Blink accessibility caches, materialized by CDP-driven automation.
|
|
49
|
+
*/
|
|
50
|
+
const AX_NAME_RE = /AXObjectCache|AXNodeObject|AXDirtyObject|AXComputedObject|blink::AX/;
|
|
51
|
+
/**
|
|
52
|
+
* The attached inspector's network log. Every request the page makes while CDP
|
|
53
|
+
* is attached is retained by `blink::InspectorNetworkAgent` for the lifetime of
|
|
54
|
+
* the session, so on a dev build that polls (hot reload, long-poll transports)
|
|
55
|
+
* this climbs forever. Retained by the DevToolsSession, not by the app.
|
|
56
|
+
*/
|
|
57
|
+
const CDP_NETWORK_NAME_RE = /NetworkResourcesData|XHRReplayData|InspectorNetworkAgent|PerformanceResourceTiming|^URI$/;
|
|
58
|
+
/**
|
|
59
|
+
* The inspector's performance timeline. Long-task/layout-shift/script-timing
|
|
60
|
+
* entries accumulate only because something is observing them.
|
|
61
|
+
*/
|
|
62
|
+
const CDP_PERF_NAME_RE = /PerformanceLongTaskTiming|PerformanceLongAnimationFrameTiming|PerformanceScriptTiming|TaskAttributionTiming|ScriptTimingInfo|^LayoutShift$|LayoutShiftAttribution/;
|
|
63
|
+
/**
|
|
64
|
+
* Console message storage held by the inspector. Distinct from
|
|
65
|
+
* `dev_artifacts`' console detection, which works on retainer edges: this
|
|
66
|
+
* catches the native message objects by class name.
|
|
67
|
+
*/
|
|
68
|
+
const CDP_CONSOLE_NAME_RE = /ConsoleMessage/;
|
|
69
|
+
/**
|
|
70
|
+
* Captured error stacks. `StackFrameInfo` / `ErrorStackData` balloon when
|
|
71
|
+
* something constructs `Error`s at high frequency — most often React's DEV-only
|
|
72
|
+
* `_debugStack` owner stacks (see the `reactDebugStack` detector in
|
|
73
|
+
* `dev-artifacts`), or dev-build logging that captures a stack per record.
|
|
74
|
+
*
|
|
75
|
+
* Flagged as `stack-capture` rather than asserted dev-only: a production build
|
|
76
|
+
* can legitimately grow these, so the annotation points at the likely cause
|
|
77
|
+
* instead of dismissing the row.
|
|
78
|
+
*/
|
|
79
|
+
const STACK_CAPTURE_NAME_RE = /StackFrameInfo|ErrorStackData/;
|
|
80
|
+
const KIND_LABEL = {
|
|
81
|
+
warmup: '⚙ JIT/compile warmup (not a leak)',
|
|
82
|
+
ax: '♿ a11y/CDP cache (automation artifact)',
|
|
83
|
+
'cdp-network': '🔌 CDP network-inspector retention (artifact)',
|
|
84
|
+
'cdp-perf': '🔌 CDP performance-timeline retention (artifact)',
|
|
85
|
+
'cdp-console': '🔌 CDP console retention (artifact)',
|
|
86
|
+
'stack-capture': '🧵 captured Error stacks (often React DEV _debugStack)',
|
|
87
|
+
};
|
|
88
|
+
const KIND_NOTE = {
|
|
89
|
+
warmup: '⚙️ V8 **compilation-warmup** structures (`Code`, `BytecodeArray`, `FeedbackVector`, `ScopeInfo`, `InstructionStream`, …) are growing. Exercising new code paths during a hunt JIT-compiles them, so they climb every step without being an app leak.',
|
|
90
|
+
ax: '♿ Blink **accessibility caches** (`AXObjectCacheImpl` / `AXNodeObject` / `AXDirtyObject`) are growing. These are inflated by CDP-driven automation building the a11y tree, and they co-retain detached DOM, so retainer traces can route through them and mislead.',
|
|
91
|
+
'cdp-network': '🔌 The attached inspector is retaining the **network log** (`blink::NetworkResourcesData` / `XHRReplayData` / `PerformanceResourceTiming`). Every request made while CDP is attached is held by `blink::DevToolsSession → InspectorNetworkAgent` for the session, so a dev build that polls (hot reload, long-poll transports) grows this forever. Not app memory.',
|
|
92
|
+
'cdp-perf': '🔌 The attached inspector is retaining the **performance timeline** (long-task / layout-shift / script-timing entries). These accumulate because something is observing them, not because the app leaks.',
|
|
93
|
+
'cdp-console': '🔌 The attached inspector is retaining **console messages**. Cross-check with `memlab_dev_artifacts`, which also detects console retention by retainer edge.',
|
|
94
|
+
'stack-capture': '🧵 **Captured Error stacks** (`StackFrameInfo` / `ErrorStackData`) are growing. The usual cause is React DEV `_debugStack` owner stacks or dev-build logging that captures a stack per record — both dev-build-only. `memlab_dev_artifacts` reports the `React DEV owner stack` category when that is the source.',
|
|
95
|
+
};
|
|
96
|
+
export function artifactLabel(kind) {
|
|
97
|
+
return KIND_LABEL[kind];
|
|
98
|
+
}
|
|
99
|
+
export function artifactNote(kind) {
|
|
100
|
+
return KIND_NOTE[kind];
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Content signatures of strings that do NOT ship: the CDP-driven bridge the
|
|
104
|
+
* agent injects to observe the page (browser MCP plugin, browser-tools
|
|
105
|
+
* extension, Puppeteer helpers), and DEV-build-only framework machinery.
|
|
106
|
+
*
|
|
107
|
+
* Why this needs its own classifier, separate from `classifyArtifact`: these are
|
|
108
|
+
* matched on string CONTENT, not on a class name, and they are not reachable
|
|
109
|
+
* from a dev *global*, so neither the class-name registry above nor
|
|
110
|
+
* `dev_artifacts`' root scan sees them.
|
|
111
|
+
*
|
|
112
|
+
* Why it matters: on a measured WA Web round the injected bridge bundle appeared
|
|
113
|
+
* as 64 copies of one 235.6 KB string — 14.7 MB total, the single largest entry
|
|
114
|
+
* in `duplicated_strings` and the single largest "opportunity" in
|
|
115
|
+
* `intern_opportunities`. Interning it would save the application nothing,
|
|
116
|
+
* because none of it ships. Reporting it as a win is worse than not reporting it
|
|
117
|
+
* at all: it sends a fix author after the test rig. The React DEV entries below
|
|
118
|
+
* were the same story a round later: 4,529 `_debugStack` Error stacks, 3.0 MB,
|
|
119
|
+
* none of which exist in a production build.
|
|
120
|
+
*
|
|
121
|
+
* Every pattern here has to be specific enough that application source cannot
|
|
122
|
+
* match it — a false "this doesn't ship" hides a real win, which is the more
|
|
123
|
+
* expensive direction to be wrong in for THIS classifier (the opposite of
|
|
124
|
+
* `classifyArtifact`, where a false artifact hides a real leak).
|
|
125
|
+
*/
|
|
126
|
+
const NON_PRODUCTION_STRING_SIGNATURES = [
|
|
127
|
+
{
|
|
128
|
+
// The UMD/CommonJS prologue every bundled bridge is wrapped in. Anchored at
|
|
129
|
+
// the start and required to reach `commonjsGlobal` within the prologue, so
|
|
130
|
+
// ordinary application source strings do not match.
|
|
131
|
+
re: /^\(function\s*\(exports\)\s*\{[\s\S]{0,400}commonjsGlobal/,
|
|
132
|
+
kind: 'harness',
|
|
133
|
+
what: 'injected CommonJS bundle (automation/devtools bridge)',
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
re: /^\s*at (?:Object\.)?__PUPPETEER|puppeteer_evaluation_script/,
|
|
137
|
+
kind: 'harness',
|
|
138
|
+
what: 'Puppeteer evaluation frame',
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
// react-dom DEV names the frames it inserts into owner stacks
|
|
142
|
+
// `react-stack-top-frame` / `react-stack-bottom-frame`, in hyphenated and
|
|
143
|
+
// underscored spellings depending on the build. BOTH ends must be matched:
|
|
144
|
+
// measured on one 2.5M-node capture, `react-stack-top-frame` appears 56
|
|
145
|
+
// times and `react_stack_bottom_frame` twice, so a bottom-only pattern
|
|
146
|
+
// misses the dominant form and classifies most DEV owner stacks as
|
|
147
|
+
// production. The hyphenated spelling cannot be a JS identifier, so it only
|
|
148
|
+
// ever appears inside a captured stack string.
|
|
149
|
+
re: /react[-_]stack[-_](?:top|bottom)[-_]frame/,
|
|
150
|
+
kind: 'dev-build',
|
|
151
|
+
what: 'React DEV owner stack (_debugStack) — not captured in production',
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
// A compiled DEV module's Fast Refresh epilogue. Requires the call form, so
|
|
155
|
+
// a string that merely mentions the identifier does not match.
|
|
156
|
+
re: /\$RefreshReg\$\(|\$RefreshSig\$\(/,
|
|
157
|
+
kind: 'dev-build',
|
|
158
|
+
what: 'React Fast Refresh instrumentation in compiled source (DEV bundle only)',
|
|
159
|
+
},
|
|
160
|
+
];
|
|
161
|
+
/**
|
|
162
|
+
* Classify a string VALUE as non-production (harness-injected or DEV-build
|
|
163
|
+
* only), or null when it is app content that really does ship.
|
|
164
|
+
*/
|
|
165
|
+
export function classifyNonProductionString(value) {
|
|
166
|
+
for (const { re, kind, what } of NON_PRODUCTION_STRING_SIGNATURES) {
|
|
167
|
+
if (re.test(value))
|
|
168
|
+
return { kind, what };
|
|
169
|
+
}
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Back-compatible wrapper returning just the description. Prefer
|
|
174
|
+
* {@link classifyNonProductionString} when the caller can act on the kind.
|
|
175
|
+
*/
|
|
176
|
+
export function classifyHarnessString(value) {
|
|
177
|
+
return classifyNonProductionString(value)?.what ?? null;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* React Fast Refresh module-scope registries, by the edge name that binds each
|
|
181
|
+
* one. These live in the refresh runtime's closure and are reachable only
|
|
182
|
+
* through compiled-code constant pools, so a retainer-root scan does not find
|
|
183
|
+
* them and they classify as `production` unless matched by name here. See
|
|
184
|
+
* `tools/dev-artifacts` for the measured cost of missing them.
|
|
185
|
+
*/
|
|
186
|
+
export const REACT_REFRESH_REGISTRY_EDGE_NAMES = new Set([
|
|
187
|
+
'allFamiliesByID',
|
|
188
|
+
'allFamiliesByType',
|
|
189
|
+
'allSignaturesByType',
|
|
190
|
+
'updatedFamiliesByType',
|
|
191
|
+
'pendingUpdates',
|
|
192
|
+
'helpersByRendererID',
|
|
193
|
+
'helpersByRoot',
|
|
194
|
+
'mountedRoots',
|
|
195
|
+
'failedRoots',
|
|
196
|
+
'rootElements',
|
|
197
|
+
]);
|
|
198
|
+
/**
|
|
199
|
+
* The rarest property of the react-refresh signature record. Callers gate on
|
|
200
|
+
* this before confirming the full shape, so a scan stays one name compare per
|
|
201
|
+
* edge on everything else.
|
|
202
|
+
*/
|
|
203
|
+
export const REACT_REFRESH_SIGNATURE_GATE_PROP = 'getCustomHooks';
|
|
204
|
+
const REACT_REFRESH_SIGNATURE_PROPS = [
|
|
205
|
+
'forceReset',
|
|
206
|
+
'ownKey',
|
|
207
|
+
'fullKey',
|
|
208
|
+
'getCustomHooks',
|
|
209
|
+
];
|
|
210
|
+
/**
|
|
211
|
+
* Recognize the per-type signature record react-refresh stores via
|
|
212
|
+
* `setSignature(type, key, forceReset, getCustomHooks)` — the value side of
|
|
213
|
+
* `allSignaturesByType`, shaped `{forceReset, ownKey, fullKey, getCustomHooks}`.
|
|
214
|
+
*/
|
|
215
|
+
export function isReactRefreshSignatureShape(propNames) {
|
|
216
|
+
const seen = new Set();
|
|
217
|
+
for (const name of propNames) {
|
|
218
|
+
if (REACT_REFRESH_SIGNATURE_PROPS.includes(name))
|
|
219
|
+
seen.add(name);
|
|
220
|
+
if (seen.size === REACT_REFRESH_SIGNATURE_PROPS.length)
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Recognize the parent object SHAPE of an MCP/devtools tool manifest entry.
|
|
227
|
+
*
|
|
228
|
+
* The bridge's tool definitions carry long `.description` strings — one per tool
|
|
229
|
+
* — and a per-load intern pool would happily "save" them. The shape is
|
|
230
|
+
* distinctive enough to match directly, and matching the shape (rather than the
|
|
231
|
+
* description text) keeps app strings that merely have a `description` property
|
|
232
|
+
* out of it.
|
|
233
|
+
*/
|
|
234
|
+
export function isHarnessToolManifestShape(propNames) {
|
|
235
|
+
const props = new Set(propNames);
|
|
236
|
+
return (props.has('description') &&
|
|
237
|
+
props.has('inputSchema') &&
|
|
238
|
+
(props.has('call') || props.has('handler')) &&
|
|
239
|
+
props.has('name'));
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Classify a class NAME as a known measurement artifact, or null when it is a
|
|
243
|
+
* genuine leak candidate.
|
|
244
|
+
*/
|
|
245
|
+
export function classifyArtifact(name) {
|
|
246
|
+
const bare = name.replace(/^system \/ /, '');
|
|
247
|
+
if (WARMUP_CLASS_NAMES.has(bare))
|
|
248
|
+
return 'warmup';
|
|
249
|
+
if (AX_NAME_RE.test(name))
|
|
250
|
+
return 'ax';
|
|
251
|
+
if (CDP_NETWORK_NAME_RE.test(bare))
|
|
252
|
+
return 'cdp-network';
|
|
253
|
+
if (CDP_PERF_NAME_RE.test(bare))
|
|
254
|
+
return 'cdp-perf';
|
|
255
|
+
if (CDP_CONSOLE_NAME_RE.test(bare))
|
|
256
|
+
return 'cdp-console';
|
|
257
|
+
if (STACK_CAPTURE_NAME_RE.test(bare))
|
|
258
|
+
return 'stack-capture';
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=artifact-classes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-classes.js","sourceRoot":"","sources":["../src/artifact-classes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @format
|
|
8
|
+
* @oncall memory_lab
|
|
9
|
+
*/
|
|
10
|
+
import type { SnapshotEnv } from './heap-state.js';
|
|
11
|
+
/**
|
|
12
|
+
* Was this snapshot captured with numeric-value capture on?
|
|
13
|
+
*
|
|
14
|
+
* Background: `heap number` is a perennial top grower, and the standing advice
|
|
15
|
+
* was "that is probably a capture artifact — check whether you captured with
|
|
16
|
+
* numeric values on". That advice pushed a decision onto the caller that the
|
|
17
|
+
* caller usually cannot answer (the snapshot may be days old, or captured by
|
|
18
|
+
* someone else), and it rested on a mechanism that was never measured.
|
|
19
|
+
*
|
|
20
|
+
* It was measured for this change, with matched pairs — the same program/page,
|
|
21
|
+
* two snapshots differing ONLY in the `captureNumericValue` CDP flag:
|
|
22
|
+
*
|
|
23
|
+
* - **Node.js** (`inspector` → `HeapProfiler.takeHeapSnapshot`): the flag adds
|
|
24
|
+
* `smi number` nodes and nothing else. Off: 10,100 number nodes, zero of them
|
|
25
|
+
* `smi number`. On: 10,390, of which 290 `smi number`. `heap number` was
|
|
26
|
+
* IDENTICAL at 10,100 in both. Smis are immediate values, not heap objects,
|
|
27
|
+
* so they only become graph nodes when the flag asks V8 to materialize them —
|
|
28
|
+
* which makes their presence a sound detector here.
|
|
29
|
+
* - **Chrome**: no detectable difference at all. On a page holding 20,000
|
|
30
|
+
* objects each with a double and a Smi field, on and off produced the same
|
|
31
|
+
* populations to the node: 40,026 `heap number`, 20,000 `smi number`, 1,063
|
|
32
|
+
* `int`. Chrome emits `smi number` either way, so the Node detector does not
|
|
33
|
+
* transfer, and no other field varies.
|
|
34
|
+
*
|
|
35
|
+
* Neither environment ever encodes the numeric VALUE in the node name (0
|
|
36
|
+
* value-named number nodes across all four snapshots), so name-based detection
|
|
37
|
+
* — the approach a previous round tried and rejected — cannot work in principle.
|
|
38
|
+
*
|
|
39
|
+
* Two consequences, both of which change what the tools should say:
|
|
40
|
+
* 1. For a BROWSER snapshot the question is not merely unanswerable, it is
|
|
41
|
+
* moot: the flag changes nothing, so `heap number` growth in a browser
|
|
42
|
+
* capture is never a numeric-capture artifact and must be investigated as
|
|
43
|
+
* real.
|
|
44
|
+
* 2. The old claim that the mode "emits one node per distinct number and ~3x
|
|
45
|
+
* inflates the graph" is not what was measured in either environment.
|
|
46
|
+
*/
|
|
47
|
+
export type NumericCaptureMode = 'on' | 'off' | 'not-applicable' | 'unknown';
|
|
48
|
+
export interface NumericCaptureVerdict {
|
|
49
|
+
mode: NumericCaptureMode;
|
|
50
|
+
/** One sentence stating the answer, for direct inclusion in a tool result. */
|
|
51
|
+
note: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* @param env which runtime produced the snapshot
|
|
55
|
+
* @param hasSmiNumberNodes whether any `smi number` node is present
|
|
56
|
+
*/
|
|
57
|
+
export declare function classifyNumericCapture(env: SnapshotEnv, hasSmiNumberNodes: boolean): NumericCaptureVerdict;
|
|
58
|
+
/** Class-histogram key for the marker node type, as `type::name`. */
|
|
59
|
+
export declare const SMI_NUMBER_CLASS_KEY = "number::smi number";
|
|
60
|
+
//# sourceMappingURL=capture-mode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture-mode.d.ts","sourceRoot":"","sources":["../src/capture-mode.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,iBAAiB,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,KAAK,GAAG,gBAAgB,GAAG,SAAS,CAAC;AAE7E,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,kBAAkB,CAAC;IACzB,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,WAAW,EAChB,iBAAiB,EAAE,OAAO,GACzB,qBAAqB,CAsBvB;AAED,qEAAqE;AACrE,eAAO,MAAM,oBAAoB,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @format
|
|
8
|
+
* @oncall memory_lab
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* @param env which runtime produced the snapshot
|
|
12
|
+
* @param hasSmiNumberNodes whether any `smi number` node is present
|
|
13
|
+
*/
|
|
14
|
+
export function classifyNumericCapture(env, hasSmiNumberNodes) {
|
|
15
|
+
if (env === 'browser') {
|
|
16
|
+
return {
|
|
17
|
+
mode: 'not-applicable',
|
|
18
|
+
note: 'This is a **browser** capture, where `capture_numeric_value` makes no difference to the snapshot: a matched pair taken with the flag on and off produced identical number-node populations (40,026 `heap number` / 20,000 `smi number` in both). So `heap number` growth here is **not** a numeric-capture artifact — treat it as real and trace it with `memlab_retainer_summary` on `heap number`.',
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
if (env === 'node') {
|
|
22
|
+
return hasSmiNumberNodes
|
|
23
|
+
? {
|
|
24
|
+
mode: 'on',
|
|
25
|
+
note: 'This **Node.js** capture was taken with **numeric-value capture ON** — `smi number` nodes are present, and V8 only materializes Smis as graph nodes in that mode. `smi number` growth is therefore a capture artifact. `heap number` is emitted either way (a matched pair had an identical `heap number` count with the flag on and off), so `heap number` growth is still worth investigating.',
|
|
26
|
+
}
|
|
27
|
+
: {
|
|
28
|
+
mode: 'off',
|
|
29
|
+
note: 'This **Node.js** capture was taken with **numeric-value capture OFF** (no `smi number` nodes present). `heap number` nodes are therefore ordinary boxed doubles that V8 allocates anyway — this growth may be real, so investigate it rather than dismissing it.',
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
mode: 'unknown',
|
|
34
|
+
note: 'The runtime that produced this snapshot could not be identified, so the numeric-capture mode cannot be stated. In browser captures the flag makes no difference; in Node.js captures it adds `smi number` nodes.',
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** Class-histogram key for the marker node type, as `type::name`. */
|
|
38
|
+
export const SMI_NUMBER_CLASS_KEY = 'number::smi number';
|
|
39
|
+
//# sourceMappingURL=capture-mode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture-mode.js","sourceRoot":"","sources":["../src/capture-mode.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgDH;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,GAAgB,EAChB,iBAA0B;IAE1B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO;YACL,IAAI,EAAE,gBAAgB;YACtB,IAAI,EAAE,sYAAsY;SAC7Y,CAAC;IACJ,CAAC;IACD,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,OAAO,iBAAiB;YACtB,CAAC,CAAC;gBACE,IAAI,EAAE,IAAI;gBACV,IAAI,EAAE,kYAAkY;aACzY;YACH,CAAC,CAAC;gBACE,IAAI,EAAE,KAAK;gBACX,IAAI,EAAE,kQAAkQ;aACzQ,CAAC;IACR,CAAC;IACD,OAAO;QACL,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,kNAAkN;KACzN,CAAC;AACJ,CAAC;AAED,qEAAqE;AACrE,MAAM,CAAC,MAAM,oBAAoB,GAAG,oBAAoB,CAAC"}
|
package/dist/guardrail.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guardrail.d.ts","sourceRoot":"","sources":["../src/guardrail.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"guardrail.d.ts","sourceRoot":"","sources":["../src/guardrail.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAavE;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAwDhE"}
|
package/dist/guardrail.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { beginAnalysisBudget, endAnalysisBudget, getAnalysisTimeoutMs, activeElapsedMs, ScanTimeoutError, } from './analysis-budget.js';
|
|
11
11
|
import { toolResult } from './utils.js';
|
|
12
|
+
import { recordToolHandler } from './tool-registry.js';
|
|
12
13
|
/**
|
|
13
14
|
* Install a process-wide wall-clock guardrail around every tool call.
|
|
14
15
|
*
|
|
@@ -29,6 +30,18 @@ export function installAnalysisGuardrail(server) {
|
|
|
29
30
|
const handler = toolArgs[lastIdx];
|
|
30
31
|
if (typeof handler === 'function') {
|
|
31
32
|
const inner = handler;
|
|
33
|
+
// Index the raw handler plus its zod shape so tools can dispatch to each
|
|
34
|
+
// other in-process without re-entering the budget, and without losing the
|
|
35
|
+
// schema defaults the SDK would normally apply (see tool-registry.ts).
|
|
36
|
+
// Registration is tool(name, description?, shape?, handler): the shape is
|
|
37
|
+
// whatever plain object sits immediately before the handler.
|
|
38
|
+
const maybeShape = lastIdx > 0 ? toolArgs[lastIdx - 1] : undefined;
|
|
39
|
+
const shape = maybeShape != null &&
|
|
40
|
+
typeof maybeShape === 'object' &&
|
|
41
|
+
!Array.isArray(maybeShape)
|
|
42
|
+
? maybeShape
|
|
43
|
+
: null;
|
|
44
|
+
recordToolHandler(name, inner, shape);
|
|
32
45
|
toolArgs[lastIdx] = async (...hArgs) => {
|
|
33
46
|
// The SDK calls handler(args, extra) for schema tools, handler(extra)
|
|
34
47
|
// otherwise. Read an optional per-call timeout_ms off the params.
|
package/dist/guardrail.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guardrail.js","sourceRoot":"","sources":["../src/guardrail.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,gBAAgB,GACjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAC,UAAU,EAAC,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"guardrail.js","sourceRoot":"","sources":["../src/guardrail.ts"],"names":[],"mappings":"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"}
|
package/dist/heap-state.d.ts
CHANGED
|
@@ -22,7 +22,30 @@ export interface SnapshotMetadata {
|
|
|
22
22
|
edgeCount: number;
|
|
23
23
|
totalSize: number;
|
|
24
24
|
env: SnapshotEnv;
|
|
25
|
+
/**
|
|
26
|
+
* True when the snapshot was parsed WITHOUT memlab's path/dominator pass
|
|
27
|
+
* (`memlab_load_snapshot({light: true})`). Roughly halves load time, at the
|
|
28
|
+
* cost of `retainedSize`, `dominatorNode` and `pathEdge` being absent — see
|
|
29
|
+
* {@link getSnapshot}.
|
|
30
|
+
*/
|
|
31
|
+
light: boolean;
|
|
25
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Drop the least-recently-used resident snapshot, never the current one.
|
|
35
|
+
* Returns its metadata, or null when there is nothing else to evict.
|
|
36
|
+
*
|
|
37
|
+
* Used by the loader's memory-headroom guard: with `keep_previous`, several
|
|
38
|
+
* full graphs stay resident, and the load that tips the process over is the one
|
|
39
|
+
* that dies — taking every resident snapshot with it. Evicting the coldest one
|
|
40
|
+
* first turns an OOM crash into a slower session.
|
|
41
|
+
*/
|
|
42
|
+
export declare function evictLeastRecentlyUsed(): SnapshotMetadata | null;
|
|
43
|
+
/**
|
|
44
|
+
* Returns the mutable scratch object for the current snapshot, creating it on
|
|
45
|
+
* first use. Node ids and any derived index are only valid for the snapshot they
|
|
46
|
+
* were built from, so the scratch is keyed to the active handle.
|
|
47
|
+
*/
|
|
48
|
+
export declare function getEvalScratch(): Record<string, unknown>;
|
|
26
49
|
/**
|
|
27
50
|
* Session-level output controls to trim repeated boilerplate tokens.
|
|
28
51
|
* - `quietHeader`: when true, the per-call snapshot header is printed only
|
|
@@ -42,7 +65,52 @@ export declare function setSessionConfig(patch: Partial<SessionConfig>): Session
|
|
|
42
65
|
* whether to prepend the snapshot header.
|
|
43
66
|
*/
|
|
44
67
|
export declare function shouldEmitHeader(): boolean;
|
|
45
|
-
export declare function
|
|
68
|
+
export declare function shouldEmitNote(key: string): boolean;
|
|
69
|
+
/** True if `key` has already been emitted, without marking it. */
|
|
70
|
+
export declare function noteAlreadyEmitted(key: string): boolean;
|
|
71
|
+
/** Force the standing notes to print again (used by `repeat_notes`). */
|
|
72
|
+
export declare function resetEmittedNotes(): void;
|
|
73
|
+
/**
|
|
74
|
+
* Named results saved from `memlab_eval` (`save_as` / `helpers.save`).
|
|
75
|
+
*
|
|
76
|
+
* SESSION-scoped, deliberately not snapshot-scoped. Comparing a baseline scan
|
|
77
|
+
* against a final scan is the central job of a leak hunt, and the previous
|
|
78
|
+
* per-snapshot scratch dropped the baseline the moment the next rung was loaded
|
|
79
|
+
* — i.e. exactly when it became useful. The handle each value was saved against
|
|
80
|
+
* is recorded alongside it, because node ids are per-capture: `helpers.load`
|
|
81
|
+
* refuses a cross-snapshot read unless the caller says the value is portable.
|
|
82
|
+
*/
|
|
83
|
+
interface SavedResult {
|
|
84
|
+
value: unknown;
|
|
85
|
+
handle: string;
|
|
86
|
+
}
|
|
87
|
+
export declare function setSavedResult(name: string, value: unknown, handle: string): void;
|
|
88
|
+
export declare function getSavedResult(name: string): SavedResult | undefined;
|
|
89
|
+
export declare function listSavedResults(): Array<{
|
|
90
|
+
name: string;
|
|
91
|
+
handle: string;
|
|
92
|
+
}>;
|
|
93
|
+
/**
|
|
94
|
+
* The current snapshot.
|
|
95
|
+
*
|
|
96
|
+
* A LIGHT snapshot (loaded with `light: true`) has no dominator tree, no
|
|
97
|
+
* retained sizes and no shortest-path edges. On such a snapshot `retainedSize`
|
|
98
|
+
* reads 0 and `dominatorNode` / `pathEdge` are absent — which does not throw, it
|
|
99
|
+
* silently produces zeros and empty traces. A tool that reported those as
|
|
100
|
+
* results would be confidently wrong, which is worse than refusing.
|
|
101
|
+
*
|
|
102
|
+
* So light access is DENY-BY-DEFAULT and must be opted into per call site with
|
|
103
|
+
* `{allowLight: true}`, by tools that read only counts, names, types, self
|
|
104
|
+
* sizes, string values or edges. Enforcing it here rather than in the tool
|
|
105
|
+
* wrapper is deliberate: this is the one funnel every tool goes through,
|
|
106
|
+
* including tools dispatched in-process by `memlab_batch`, which bypass the
|
|
107
|
+
* guardrail wrapper entirely.
|
|
108
|
+
*/
|
|
109
|
+
export declare function getSnapshot(opts?: {
|
|
110
|
+
allowLight?: boolean;
|
|
111
|
+
}): IHeapSnapshot;
|
|
112
|
+
/** True when the current snapshot was loaded without the dominator pass. */
|
|
113
|
+
export declare function isLightSnapshot(): boolean;
|
|
46
114
|
export declare function getFilePath(): string | null;
|
|
47
115
|
export declare function getSnapshotEnv(): SnapshotEnv;
|
|
48
116
|
export declare function getSnapshotMetadata(): SnapshotMetadata | null;
|
|
@@ -57,7 +125,9 @@ export declare function getSnapshotMetadata(): SnapshotMetadata | null;
|
|
|
57
125
|
* preserving the single-resident memory profile. When false, keep
|
|
58
126
|
* previously-loaded snapshots resident for diffing/comparison.
|
|
59
127
|
*/
|
|
60
|
-
export declare function setSnapshot(snapshot: IHeapSnapshot, filePath: string, metadata: Omit<SnapshotMetadata, 'filePath' | 'handle'
|
|
128
|
+
export declare function setSnapshot(snapshot: IHeapSnapshot, filePath: string, metadata: Omit<SnapshotMetadata, 'filePath' | 'handle' | 'light'> & {
|
|
129
|
+
light?: boolean;
|
|
130
|
+
}, opts?: {
|
|
61
131
|
alias?: string;
|
|
62
132
|
replace?: boolean;
|
|
63
133
|
}): SnapshotMetadata;
|
|
@@ -69,9 +139,26 @@ export declare function listSnapshots(): SnapshotMetadata[];
|
|
|
69
139
|
* in P2403258184 §3).
|
|
70
140
|
*/
|
|
71
141
|
export declare function clearAllSnapshots(): void;
|
|
142
|
+
/**
|
|
143
|
+
* A resident snapshot loaded from this exact path, if any.
|
|
144
|
+
*
|
|
145
|
+
* The point of a snapshot cache is to not re-parse a file this process already
|
|
146
|
+
* has in memory; that check has to key on the resolved path, since the handle is
|
|
147
|
+
* derived from the file name and may have been disambiguated.
|
|
148
|
+
*/
|
|
149
|
+
export declare function findResidentByPath(filePath: string): SnapshotMetadata | null;
|
|
150
|
+
/**
|
|
151
|
+
* Drop every resident snapshot except `handle`, which becomes current.
|
|
152
|
+
*
|
|
153
|
+
* Used by the load cache-hit path so a hit is indistinguishable from a real load
|
|
154
|
+
* apart from speed: a replace-mode load unloads the others, and a hit must do
|
|
155
|
+
* the same or the two paths leave different state behind.
|
|
156
|
+
*/
|
|
157
|
+
export declare function retainOnlySnapshot(handle: string): boolean;
|
|
72
158
|
export declare function getCurrentHandle(): string | null;
|
|
73
159
|
export declare function getSnapshotByHandle(handle: string): IHeapSnapshot | null;
|
|
74
160
|
export declare function getMetadataByHandle(handle: string): SnapshotMetadata | null;
|
|
75
161
|
export declare function setCurrentSnapshot(handle: string): boolean;
|
|
76
162
|
export declare function removeSnapshot(handle: string): boolean;
|
|
163
|
+
export {};
|
|
77
164
|
//# sourceMappingURL=heap-state.d.ts.map
|
package/dist/heap-state.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"heap-state.d.ts","sourceRoot":"","sources":["../src/heap-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,cAAc,CAAC;AAGhD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AAgCzD,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"heap-state.d.ts","sourceRoot":"","sources":["../src/heap-state.ts"],"names":[],"mappings":"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"}
|