@memlab/mcp-server 2.18.1 → 2.86.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.
Files changed (374) hide show
  1. package/README.md +30 -16
  2. package/bin/.eslintrc.js +26 -0
  3. package/bin/memlab-cli.js +313 -0
  4. package/dist/anonymized-snapshot.d.ts +75 -0
  5. package/dist/anonymized-snapshot.d.ts.map +1 -0
  6. package/dist/anonymized-snapshot.js +101 -0
  7. package/dist/anonymized-snapshot.js.map +1 -0
  8. package/dist/artifact-classes.d.ts +86 -0
  9. package/dist/artifact-classes.d.ts.map +1 -0
  10. package/dist/artifact-classes.js +261 -0
  11. package/dist/artifact-classes.js.map +1 -0
  12. package/dist/capture-mode.d.ts +60 -0
  13. package/dist/capture-mode.d.ts.map +1 -0
  14. package/dist/capture-mode.js +39 -0
  15. package/dist/capture-mode.js.map +1 -0
  16. package/dist/eval-hints.d.ts +41 -0
  17. package/dist/eval-hints.d.ts.map +1 -0
  18. package/dist/eval-hints.js +115 -0
  19. package/dist/eval-hints.js.map +1 -0
  20. package/dist/guardrail.d.ts.map +1 -1
  21. package/dist/guardrail.js +13 -0
  22. package/dist/guardrail.js.map +1 -1
  23. package/dist/heap-budget.d.ts +32 -0
  24. package/dist/heap-budget.d.ts.map +1 -0
  25. package/dist/heap-budget.js +90 -0
  26. package/dist/heap-budget.js.map +1 -0
  27. package/dist/heap-shapes.d.ts +148 -0
  28. package/dist/heap-shapes.d.ts.map +1 -0
  29. package/dist/heap-shapes.js +193 -0
  30. package/dist/heap-shapes.js.map +1 -0
  31. package/dist/heap-state.d.ts +109 -2
  32. package/dist/heap-state.d.ts.map +1 -1
  33. package/dist/heap-state.js +194 -3
  34. package/dist/heap-state.js.map +1 -1
  35. package/dist/index.js +102 -1
  36. package/dist/index.js.map +1 -1
  37. package/dist/progress.d.ts +25 -0
  38. package/dist/progress.d.ts.map +1 -0
  39. package/dist/progress.js +46 -0
  40. package/dist/progress.js.map +1 -0
  41. package/dist/react-shapes.d.ts +42 -0
  42. package/dist/react-shapes.d.ts.map +1 -0
  43. package/dist/react-shapes.js +149 -0
  44. package/dist/react-shapes.js.map +1 -0
  45. package/dist/result-handles.d.ts +11 -0
  46. package/dist/result-handles.d.ts.map +1 -0
  47. package/dist/result-handles.js +77 -0
  48. package/dist/result-handles.js.map +1 -0
  49. package/dist/server-version.d.ts +19 -0
  50. package/dist/server-version.d.ts.map +1 -0
  51. package/dist/server-version.js +19 -0
  52. package/dist/server-version.js.map +1 -0
  53. package/dist/snapshot-borrow.d.ts +67 -0
  54. package/dist/snapshot-borrow.d.ts.map +1 -0
  55. package/dist/snapshot-borrow.js +113 -0
  56. package/dist/snapshot-borrow.js.map +1 -0
  57. package/dist/string-index.d.ts +55 -0
  58. package/dist/string-index.d.ts.map +1 -0
  59. package/dist/string-index.js +99 -0
  60. package/dist/string-index.js.map +1 -0
  61. package/dist/tool-registry.d.ts +42 -0
  62. package/dist/tool-registry.d.ts.map +1 -0
  63. package/dist/tool-registry.js +20 -0
  64. package/dist/tool-registry.js.map +1 -0
  65. package/dist/tools/analyze-run.d.ts +12 -0
  66. package/dist/tools/analyze-run.d.ts.map +1 -0
  67. package/dist/tools/analyze-run.js +404 -0
  68. package/dist/tools/analyze-run.js.map +1 -0
  69. package/dist/tools/anonymize-snapshot.d.ts +12 -0
  70. package/dist/tools/anonymize-snapshot.d.ts.map +1 -0
  71. package/dist/tools/anonymize-snapshot.js +159 -0
  72. package/dist/tools/anonymize-snapshot.js.map +1 -0
  73. package/dist/tools/app-config.d.ts +12 -0
  74. package/dist/tools/app-config.d.ts.map +1 -0
  75. package/dist/tools/app-config.js +217 -0
  76. package/dist/tools/app-config.js.map +1 -0
  77. package/dist/tools/app-heap.d.ts +30 -0
  78. package/dist/tools/app-heap.d.ts.map +1 -0
  79. package/dist/tools/app-heap.js +106 -0
  80. package/dist/tools/app-heap.js.map +1 -0
  81. package/dist/tools/artifact-budget.d.ts +12 -0
  82. package/dist/tools/artifact-budget.d.ts.map +1 -0
  83. package/dist/tools/artifact-budget.js +219 -0
  84. package/dist/tools/artifact-budget.js.map +1 -0
  85. package/dist/tools/async-census.d.ts +12 -0
  86. package/dist/tools/async-census.d.ts.map +1 -0
  87. package/dist/tools/async-census.js +243 -0
  88. package/dist/tools/async-census.js.map +1 -0
  89. package/dist/tools/auto-investigate.d.ts.map +1 -1
  90. package/dist/tools/auto-investigate.js +54 -5
  91. package/dist/tools/auto-investigate.js.map +1 -1
  92. package/dist/tools/batch.d.ts +12 -0
  93. package/dist/tools/batch.d.ts.map +1 -0
  94. package/dist/tools/batch.js +196 -0
  95. package/dist/tools/batch.js.map +1 -0
  96. package/dist/tools/cache-analysis.d.ts +15 -0
  97. package/dist/tools/cache-analysis.d.ts.map +1 -1
  98. package/dist/tools/cache-analysis.js +240 -14
  99. package/dist/tools/cache-analysis.js.map +1 -1
  100. package/dist/tools/census-diff.d.ts +55 -0
  101. package/dist/tools/census-diff.d.ts.map +1 -0
  102. package/dist/tools/census-diff.js +228 -0
  103. package/dist/tools/census-diff.js.map +1 -0
  104. package/dist/tools/chain-walk.d.ts +12 -0
  105. package/dist/tools/chain-walk.d.ts.map +1 -0
  106. package/dist/tools/chain-walk.js +184 -0
  107. package/dist/tools/chain-walk.js.map +1 -0
  108. package/dist/tools/class-histogram.d.ts.map +1 -1
  109. package/dist/tools/class-histogram.js +14 -3
  110. package/dist/tools/class-histogram.js.map +1 -1
  111. package/dist/tools/collection-diff.d.ts +44 -0
  112. package/dist/tools/collection-diff.d.ts.map +1 -0
  113. package/dist/tools/collection-diff.js +343 -0
  114. package/dist/tools/collection-diff.js.map +1 -0
  115. package/dist/tools/collection-trend.d.ts +55 -0
  116. package/dist/tools/collection-trend.d.ts.map +1 -0
  117. package/dist/tools/collection-trend.js +315 -0
  118. package/dist/tools/collection-trend.js.map +1 -0
  119. package/dist/tools/detached-dom.d.ts +5 -0
  120. package/dist/tools/detached-dom.d.ts.map +1 -1
  121. package/dist/tools/detached-dom.js +368 -22
  122. package/dist/tools/detached-dom.js.map +1 -1
  123. package/dist/tools/dev-artifacts.d.ts +62 -6
  124. package/dist/tools/dev-artifacts.d.ts.map +1 -1
  125. package/dist/tools/dev-artifacts.js +685 -24
  126. package/dist/tools/dev-artifacts.js.map +1 -1
  127. package/dist/tools/diff-snapshots.d.ts.map +1 -1
  128. package/dist/tools/diff-snapshots.js +18 -2
  129. package/dist/tools/diff-snapshots.js.map +1 -1
  130. package/dist/tools/dom-audit.d.ts +37 -0
  131. package/dist/tools/dom-audit.d.ts.map +1 -0
  132. package/dist/tools/dom-audit.js +247 -0
  133. package/dist/tools/dom-audit.js.map +1 -0
  134. package/dist/tools/dominator-attribution.d.ts +12 -0
  135. package/dist/tools/dominator-attribution.d.ts.map +1 -0
  136. package/dist/tools/dominator-attribution.js +189 -0
  137. package/dist/tools/dominator-attribution.js.map +1 -0
  138. package/dist/tools/dominator-chain.d.ts +12 -0
  139. package/dist/tools/dominator-chain.d.ts.map +1 -0
  140. package/dist/tools/dominator-chain.js +92 -0
  141. package/dist/tools/dominator-chain.js.map +1 -0
  142. package/dist/tools/duplicate-objects.d.ts +12 -0
  143. package/dist/tools/duplicate-objects.d.ts.map +1 -0
  144. package/dist/tools/duplicate-objects.js +172 -0
  145. package/dist/tools/duplicate-objects.js.map +1 -0
  146. package/dist/tools/duplicated-strings.d.ts.map +1 -1
  147. package/dist/tools/duplicated-strings.js +49 -40
  148. package/dist/tools/duplicated-strings.js.map +1 -1
  149. package/dist/tools/eval-across.d.ts +12 -0
  150. package/dist/tools/eval-across.d.ts.map +1 -0
  151. package/dist/tools/eval-across.js +135 -0
  152. package/dist/tools/eval-across.js.map +1 -0
  153. package/dist/tools/eval.d.ts +79 -0
  154. package/dist/tools/eval.d.ts.map +1 -1
  155. package/dist/tools/eval.js +2523 -197
  156. package/dist/tools/eval.js.map +1 -1
  157. package/dist/tools/event-listener-leaks.d.ts.map +1 -1
  158. package/dist/tools/event-listener-leaks.js +42 -17
  159. package/dist/tools/event-listener-leaks.js.map +1 -1
  160. package/dist/tools/event-registry.d.ts.map +1 -1
  161. package/dist/tools/event-registry.js +42 -8
  162. package/dist/tools/event-registry.js.map +1 -1
  163. package/dist/tools/explain-delta.d.ts +12 -0
  164. package/dist/tools/explain-delta.d.ts.map +1 -0
  165. package/dist/tools/explain-delta.js +221 -0
  166. package/dist/tools/explain-delta.js.map +1 -0
  167. package/dist/tools/find-nodes-by-class.d.ts.map +1 -1
  168. package/dist/tools/find-nodes-by-class.js +112 -13
  169. package/dist/tools/find-nodes-by-class.js.map +1 -1
  170. package/dist/tools/finding-index.d.ts +203 -0
  171. package/dist/tools/finding-index.d.ts.map +1 -0
  172. package/dist/tools/finding-index.js +566 -0
  173. package/dist/tools/finding-index.js.map +1 -0
  174. package/dist/tools/for-each.d.ts.map +1 -1
  175. package/dist/tools/for-each.js +15 -3
  176. package/dist/tools/for-each.js.map +1 -1
  177. package/dist/tools/get-referrers.d.ts.map +1 -1
  178. package/dist/tools/get-referrers.js +17 -0
  179. package/dist/tools/get-referrers.js.map +1 -1
  180. package/dist/tools/get-value.d.ts +16 -0
  181. package/dist/tools/get-value.d.ts.map +1 -1
  182. package/dist/tools/get-value.js +96 -2
  183. package/dist/tools/get-value.js.map +1 -1
  184. package/dist/tools/hunt-report.d.ts +12 -0
  185. package/dist/tools/hunt-report.d.ts.map +1 -0
  186. package/dist/tools/hunt-report.js +186 -0
  187. package/dist/tools/hunt-report.js.map +1 -0
  188. package/dist/tools/hypothesis.d.ts +12 -0
  189. package/dist/tools/hypothesis.d.ts.map +1 -0
  190. package/dist/tools/hypothesis.js +280 -0
  191. package/dist/tools/hypothesis.js.map +1 -0
  192. package/dist/tools/id-space-audit.d.ts +12 -0
  193. package/dist/tools/id-space-audit.d.ts.map +1 -0
  194. package/dist/tools/id-space-audit.js +262 -0
  195. package/dist/tools/id-space-audit.js.map +1 -0
  196. package/dist/tools/identify.d.ts +12 -0
  197. package/dist/tools/identify.d.ts.map +1 -0
  198. package/dist/tools/identify.js +205 -0
  199. package/dist/tools/identify.js.map +1 -0
  200. package/dist/tools/identity-diff.d.ts +12 -0
  201. package/dist/tools/identity-diff.d.ts.map +1 -0
  202. package/dist/tools/identity-diff.js +188 -0
  203. package/dist/tools/identity-diff.js.map +1 -0
  204. package/dist/tools/intern-opportunities.d.ts.map +1 -1
  205. package/dist/tools/intern-opportunities.js +116 -50
  206. package/dist/tools/intern-opportunities.js.map +1 -1
  207. package/dist/tools/ladder-probe.d.ts +65 -0
  208. package/dist/tools/ladder-probe.d.ts.map +1 -0
  209. package/dist/tools/ladder-probe.js +445 -0
  210. package/dist/tools/ladder-probe.js.map +1 -0
  211. package/dist/tools/ladder.d.ts +33 -0
  212. package/dist/tools/ladder.d.ts.map +1 -0
  213. package/dist/tools/ladder.js +266 -0
  214. package/dist/tools/ladder.js.map +1 -0
  215. package/dist/tools/largest-objects.d.ts.map +1 -1
  216. package/dist/tools/largest-objects.js +6 -2
  217. package/dist/tools/largest-objects.js.map +1 -1
  218. package/dist/tools/leak-report.d.ts +35 -0
  219. package/dist/tools/leak-report.d.ts.map +1 -0
  220. package/dist/tools/leak-report.js +398 -0
  221. package/dist/tools/leak-report.js.map +1 -0
  222. package/dist/tools/load-snapshot.d.ts +29 -0
  223. package/dist/tools/load-snapshot.d.ts.map +1 -1
  224. package/dist/tools/load-snapshot.js +294 -23
  225. package/dist/tools/load-snapshot.js.map +1 -1
  226. package/dist/tools/map-entries.d.ts +12 -0
  227. package/dist/tools/map-entries.d.ts.map +1 -0
  228. package/dist/tools/map-entries.js +139 -0
  229. package/dist/tools/map-entries.js.map +1 -0
  230. package/dist/tools/match-object.d.ts +12 -0
  231. package/dist/tools/match-object.d.ts.map +1 -0
  232. package/dist/tools/match-object.js +165 -0
  233. package/dist/tools/match-object.js.map +1 -0
  234. package/dist/tools/metric.d.ts +13 -0
  235. package/dist/tools/metric.d.ts.map +1 -0
  236. package/dist/tools/metric.js +185 -0
  237. package/dist/tools/metric.js.map +1 -0
  238. package/dist/tools/module-attribution.d.ts +36 -0
  239. package/dist/tools/module-attribution.d.ts.map +1 -0
  240. package/dist/tools/module-attribution.js +235 -0
  241. package/dist/tools/module-attribution.js.map +1 -0
  242. package/dist/tools/next-measurement.d.ts +26 -0
  243. package/dist/tools/next-measurement.d.ts.map +1 -0
  244. package/dist/tools/next-measurement.js +149 -0
  245. package/dist/tools/next-measurement.js.map +1 -0
  246. package/dist/tools/object-cost-breakdown.d.ts.map +1 -1
  247. package/dist/tools/object-cost-breakdown.js +64 -0
  248. package/dist/tools/object-cost-breakdown.js.map +1 -1
  249. package/dist/tools/object-shape.d.ts.map +1 -1
  250. package/dist/tools/object-shape.js +53 -5
  251. package/dist/tools/object-shape.js.map +1 -1
  252. package/dist/tools/population-diff.d.ts +57 -0
  253. package/dist/tools/population-diff.d.ts.map +1 -0
  254. package/dist/tools/population-diff.js +338 -0
  255. package/dist/tools/population-diff.js.map +1 -0
  256. package/dist/tools/population-vs-owners.d.ts +12 -0
  257. package/dist/tools/population-vs-owners.d.ts.map +1 -0
  258. package/dist/tools/population-vs-owners.js +183 -0
  259. package/dist/tools/population-vs-owners.js.map +1 -0
  260. package/dist/tools/property-names.d.ts +29 -0
  261. package/dist/tools/property-names.d.ts.map +1 -0
  262. package/dist/tools/property-names.js +131 -0
  263. package/dist/tools/property-names.js.map +1 -0
  264. package/dist/tools/quick-diagnosis.d.ts.map +1 -1
  265. package/dist/tools/quick-diagnosis.js +7 -1
  266. package/dist/tools/quick-diagnosis.js.map +1 -1
  267. package/dist/tools/react-owners.d.ts +12 -0
  268. package/dist/tools/react-owners.d.ts.map +1 -0
  269. package/dist/tools/react-owners.js +167 -0
  270. package/dist/tools/react-owners.js.map +1 -0
  271. package/dist/tools/react-update-queues.d.ts +12 -0
  272. package/dist/tools/react-update-queues.d.ts.map +1 -0
  273. package/dist/tools/react-update-queues.js +173 -0
  274. package/dist/tools/react-update-queues.js.map +1 -0
  275. package/dist/tools/replicate.d.ts +49 -0
  276. package/dist/tools/replicate.d.ts.map +1 -0
  277. package/dist/tools/replicate.js +241 -0
  278. package/dist/tools/replicate.js.map +1 -0
  279. package/dist/tools/retainer-diff.d.ts +12 -0
  280. package/dist/tools/retainer-diff.d.ts.map +1 -0
  281. package/dist/tools/retainer-diff.js +168 -0
  282. package/dist/tools/retainer-diff.js.map +1 -0
  283. package/dist/tools/retainer-layers.d.ts +23 -0
  284. package/dist/tools/retainer-layers.d.ts.map +1 -0
  285. package/dist/tools/retainer-layers.js +179 -0
  286. package/dist/tools/retainer-layers.js.map +1 -0
  287. package/dist/tools/retainer-summary.d.ts +18 -0
  288. package/dist/tools/retainer-summary.d.ts.map +1 -1
  289. package/dist/tools/retainer-summary.js +210 -51
  290. package/dist/tools/retainer-summary.js.map +1 -1
  291. package/dist/tools/retainer-trace.d.ts.map +1 -1
  292. package/dist/tools/retainer-trace.js +14 -2
  293. package/dist/tools/retainer-trace.js.map +1 -1
  294. package/dist/tools/round-audit.d.ts +66 -0
  295. package/dist/tools/round-audit.d.ts.map +1 -0
  296. package/dist/tools/round-audit.js +258 -0
  297. package/dist/tools/round-audit.js.map +1 -0
  298. package/dist/tools/round-digest.d.ts +12 -0
  299. package/dist/tools/round-digest.d.ts.map +1 -0
  300. package/dist/tools/round-digest.js +190 -0
  301. package/dist/tools/round-digest.js.map +1 -0
  302. package/dist/tools/script-census.d.ts +12 -0
  303. package/dist/tools/script-census.d.ts.map +1 -0
  304. package/dist/tools/script-census.js +182 -0
  305. package/dist/tools/script-census.js.map +1 -0
  306. package/dist/tools/search-nodes.d.ts.map +1 -1
  307. package/dist/tools/search-nodes.js +5 -1
  308. package/dist/tools/search-nodes.js.map +1 -1
  309. package/dist/tools/search-strings.d.ts.map +1 -1
  310. package/dist/tools/search-strings.js +53 -7
  311. package/dist/tools/search-strings.js.map +1 -1
  312. package/dist/tools/sequence-analysis.d.ts +53 -0
  313. package/dist/tools/sequence-analysis.d.ts.map +1 -1
  314. package/dist/tools/sequence-analysis.js +313 -89
  315. package/dist/tools/sequence-analysis.js.map +1 -1
  316. package/dist/tools/server-status.d.ts.map +1 -1
  317. package/dist/tools/server-status.js +4 -1
  318. package/dist/tools/server-status.js.map +1 -1
  319. package/dist/tools/settle-check.d.ts +12 -0
  320. package/dist/tools/settle-check.d.ts.map +1 -0
  321. package/dist/tools/settle-check.js +188 -0
  322. package/dist/tools/settle-check.js.map +1 -0
  323. package/dist/tools/shape-histogram.d.ts.map +1 -1
  324. package/dist/tools/shape-histogram.js +9 -2
  325. package/dist/tools/shape-histogram.js.map +1 -1
  326. package/dist/tools/sliced-strings.d.ts.map +1 -1
  327. package/dist/tools/sliced-strings.js +2 -1
  328. package/dist/tools/sliced-strings.js.map +1 -1
  329. package/dist/tools/snapshots.d.ts.map +1 -1
  330. package/dist/tools/snapshots.js +24 -6
  331. package/dist/tools/snapshots.js.map +1 -1
  332. package/dist/tools/sparse-elements.d.ts +12 -0
  333. package/dist/tools/sparse-elements.d.ts.map +1 -0
  334. package/dist/tools/sparse-elements.js +215 -0
  335. package/dist/tools/sparse-elements.js.map +1 -0
  336. package/dist/tools/stale-collections.d.ts +17 -0
  337. package/dist/tools/stale-collections.d.ts.map +1 -1
  338. package/dist/tools/stale-collections.js +28 -0
  339. package/dist/tools/stale-collections.js.map +1 -1
  340. package/dist/tools/string-patterns.d.ts.map +1 -1
  341. package/dist/tools/string-patterns.js +7 -5
  342. package/dist/tools/string-patterns.js.map +1 -1
  343. package/dist/tools/tools-index.d.ts +12 -0
  344. package/dist/tools/tools-index.d.ts.map +1 -0
  345. package/dist/tools/tools-index.js +492 -0
  346. package/dist/tools/tools-index.js.map +1 -0
  347. package/dist/tools/trace-all.d.ts +42 -0
  348. package/dist/tools/trace-all.d.ts.map +1 -0
  349. package/dist/tools/trace-all.js +263 -0
  350. package/dist/tools/trace-all.js.map +1 -0
  351. package/dist/tools/unit-cost.d.ts +12 -0
  352. package/dist/tools/unit-cost.d.ts.map +1 -0
  353. package/dist/tools/unit-cost.js +219 -0
  354. package/dist/tools/unit-cost.js.map +1 -0
  355. package/dist/tools/verify-fix.d.ts +23 -0
  356. package/dist/tools/verify-fix.d.ts.map +1 -0
  357. package/dist/tools/verify-fix.js +219 -0
  358. package/dist/tools/verify-fix.js.map +1 -0
  359. package/dist/tools/weakmap-entries.d.ts.map +1 -1
  360. package/dist/tools/weakmap-entries.js +6 -1
  361. package/dist/tools/weakmap-entries.js.map +1 -1
  362. package/dist/tools/weakref-census.d.ts +15 -0
  363. package/dist/tools/weakref-census.d.ts.map +1 -0
  364. package/dist/tools/weakref-census.js +147 -0
  365. package/dist/tools/weakref-census.js.map +1 -0
  366. package/dist/tools/what-if.d.ts +12 -0
  367. package/dist/tools/what-if.d.ts.map +1 -0
  368. package/dist/tools/what-if.js +285 -0
  369. package/dist/tools/what-if.js.map +1 -0
  370. package/dist/utils.d.ts +238 -3
  371. package/dist/utils.d.ts.map +1 -1
  372. package/dist/utils.js +507 -15
  373. package/dist/utils.js.map +1 -1
  374. package/package.json +7 -6
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.
@@ -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;AAItC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAAiB;IACxD,MAAM,QAAQ,GAAI,MAAM,CAAC,IAAc,CAAC,IAAI,CAAC,MAAM,CAAU,CAAC;IAC7D,MAAmC,CAAC,IAAI,GAAG,CAAC,GAAG,QAAmB,EAAE,EAAE;QACrE,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;QACpC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,OAAgB,CAAC;YAC/B,QAAQ,CAAC,OAAO,CAAC,GAAG,KAAK,EAAE,GAAG,KAAgB,EAAE,EAAE;gBAChD,sEAAsE;gBACtE,kEAAkE;gBAClE,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACxB,MAAM,QAAQ,GACZ,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,YAAY,IAAI,MAAM;oBAC5D,CAAC,CAAE,MAAiC,CAAC,UAAU;oBAC/C,CAAC,CAAC,SAAS,CAAC;gBAChB,MAAM,SAAS,GAAG,oBAAoB,CACpC,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CACpD,CAAC;gBACF,mBAAmB,CAAC,SAAS,CAAC,CAAC;gBAC/B,IAAI,CAAC;oBACH,OAAO,MAAM,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC;gBAC/B,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,IAAI,CAAC,YAAY,gBAAgB,EAAE,CAAC;wBAClC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAAC;wBACjD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;wBAC3C,OAAO,UAAU,CACf,yBAAyB,IAAI,mBAAmB,KAAK,qBAAqB,GAAG,2FAA2F;4BACtK,uDAAuD;4BACvD,8GAA8G;4BAC9G,8GAA8G;4BAC9G,2JAA2J;4BAC3J,wIAAwI,KAAK,uBAAuB,CACvK,CAAC;oBACJ,CAAC;oBACD,MAAM,CAAC,CAAC;gBACV,CAAC;wBAAS,CAAC;oBACT,iBAAiB,EAAE,CAAC;gBACtB,CAAC;YACH,CAAC,CAAC;QACJ,CAAC;QACD,OAAO,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC;IAC/B,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"guardrail.js","sourceRoot":"","sources":["../src/guardrail.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
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 { IHeapSnapshot } from '@memlab/core';
11
+ import type { ArtifactKind } from './artifact-classes.js';
12
+ import type { DevOnlyTotals, DevRootCategory } from './tools/dev-artifacts.js';
13
+ export interface HeapBudget {
14
+ total: number;
15
+ app: number;
16
+ appNodes: number;
17
+ bundle: number;
18
+ code: number;
19
+ devOnly: number;
20
+ artifact: number;
21
+ /** Known-artifact self bytes split by family (warmup / ax / cdp-* / …). */
22
+ artifactByKind: Map<ArtifactKind, number>;
23
+ /** Dev-only totals split by root family, or null when no dev roots exist. */
24
+ devOnlyTotals: DevOnlyTotals | null;
25
+ }
26
+ export declare function computeHeapBudget(snapshot: IHeapSnapshot): HeapBudget;
27
+ export declare function devFamilyBytes(budget: HeapBudget): Array<{
28
+ family: DevRootCategory;
29
+ nodes: number;
30
+ selfBytes: number;
31
+ }>;
32
+ //# sourceMappingURL=heap-budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heap-budget.d.ts","sourceRoot":"","sources":["../src/heap-budget.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAY,aAAa,EAAC,MAAM,cAAc,CAAC;AAE3D,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,uBAAuB,CAAC;AAMxD,OAAO,KAAK,EAAC,aAAa,EAAE,eAAe,EAAC,MAAM,0BAA0B,CAAC;AAmB7E,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,cAAc,EAAE,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC1C,6EAA6E;IAC7E,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;CACrC;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,aAAa,GAAG,UAAU,CA2DrE;AAED,wBAAgB,cAAc,CAC5B,MAAM,EAAE,UAAU,GACjB,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAC,CAAC,CAapE"}
@@ -0,0 +1,90 @@
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 { classifyArtifact } from './artifact-classes.js';
11
+ import { collectDevRoots, computeReachableWithoutDevRoots, summarizeDevOnly, } from './tools/dev-artifacts.js';
12
+ /**
13
+ * The one bucket split of a heap into "app" and the several distinct reasons a
14
+ * byte might not be the app.
15
+ *
16
+ * Extracted so `memlab_app_heap` and `memlab_artifact_budget` cannot drift: they
17
+ * are two views of the same partition, and two implementations of "what counts
18
+ * as the app" that disagree by a few percent is worse than either one alone,
19
+ * because the disagreement is invisible in each tool's own output.
20
+ */
21
+ const CODE_TYPES = new Set(['code']);
22
+ // Bundle source text and the V8 structures that hold it. These exist because
23
+ // the app was *loaded*, not because it did anything.
24
+ const BUNDLE_NAME_RE = /ExternalStringData|InstructionStream|BytecodeArray|SharedFunctionInfo|ScopeInfo|UncompiledData|FeedbackVector|FeedbackMetadata|FeedbackCell|ClosureFeedbackCellArray|\(constant pool\)|ConstantPool/;
25
+ export function computeHeapBudget(snapshot) {
26
+ const devRoots = collectDevRoots(snapshot);
27
+ const reached = devRoots.byId.size > 0
28
+ ? computeReachableWithoutDevRoots(snapshot, devRoots)
29
+ : null;
30
+ let total = 0;
31
+ let code = 0;
32
+ let bundle = 0;
33
+ let devOnly = 0;
34
+ let artifact = 0;
35
+ let app = 0;
36
+ let appNodes = 0;
37
+ const artifactByKind = new Map();
38
+ const isDevOnly = (node) => reached != null && reached[node.nodeIndex] === 0;
39
+ snapshot.nodes.forEach((node) => {
40
+ if (node.id <= 3)
41
+ return;
42
+ const size = node.self_size;
43
+ total += size;
44
+ // Precedence matters: a node is counted once, in the most specific bucket
45
+ // that explains why it is NOT app memory.
46
+ if (isDevOnly(node)) {
47
+ devOnly += size;
48
+ return;
49
+ }
50
+ if (CODE_TYPES.has(node.type)) {
51
+ code += size;
52
+ return;
53
+ }
54
+ if (BUNDLE_NAME_RE.test(node.name)) {
55
+ bundle += size;
56
+ return;
57
+ }
58
+ const kind = classifyArtifact(node.name);
59
+ if (kind != null) {
60
+ artifact += size;
61
+ artifactByKind.set(kind, (artifactByKind.get(kind) ?? 0) + size);
62
+ return;
63
+ }
64
+ app += size;
65
+ appNodes++;
66
+ });
67
+ return {
68
+ total,
69
+ app,
70
+ appNodes,
71
+ bundle,
72
+ code,
73
+ devOnly,
74
+ artifact,
75
+ artifactByKind,
76
+ devOnlyTotals: reached != null ? summarizeDevOnly(snapshot, devRoots, reached) : null,
77
+ };
78
+ }
79
+ export function devFamilyBytes(budget) {
80
+ const out = [];
81
+ const byCategory = budget.devOnlyTotals?.byCategory;
82
+ if (byCategory == null)
83
+ return out;
84
+ for (const [family, v] of byCategory) {
85
+ out.push({ family, nodes: v.nodes, selfBytes: v.selfBytes });
86
+ }
87
+ out.sort((a, b) => b.selfBytes - a.selfBytes);
88
+ return out;
89
+ }
90
+ //# sourceMappingURL=heap-budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heap-budget.js","sourceRoot":"","sources":["../src/heap-budget.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,148 @@
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 elements-backing-store primitives, in one place.
12
+ *
13
+ * Reading an object's elements store correctly needs five separate facts, and
14
+ * each of them was got WRONG once before it was got right. They are stated here
15
+ * so no tool has to rediscover them:
16
+ *
17
+ * 1. A plain `Object` with integer keys emits an `element` edge per non-hole
18
+ * slot ON THE OWNER, small-integer values included (they point at a shared
19
+ * `smi number` node).
20
+ * 2. A `JSArray` frequently emits nothing on the owner and instead emits
21
+ * `internal` numeric edges ON THE STORE — but only for slots holding a
22
+ * heap object, so an all-SMI array reads as empty from there.
23
+ * 3. Therefore, when both sides read zero the occupancy is UNKNOWABLE: a
24
+ * `new Array(34)` of holes and an array of 34 timestamps are byte-identical
25
+ * in a snapshot. Scoring those as empty ranked 4,301 all-SMI index arrays
26
+ * as the second-largest "finding" in one run.
27
+ * 4. Capacity is `(storeBytes - 8) / slotBytes`, and `slotBytes` must be
28
+ * MEASURED. Wrong by 2x, it either invents slack that does not exist or
29
+ * classifies every dense store as a dictionary.
30
+ * 5. `maxIndex + 1 > capacity` means dictionary mode, where a hole costs
31
+ * nothing and "waste" is not defined.
32
+ */
33
+ import type { IHeapNode, IHeapSnapshot } from '@memlab/core';
34
+ /**
35
+ * Bytes of the FixedArray header preceding the first slot. Same on a
36
+ * pointer-compressed and an uncompressed heap (map + length), so only the slot
37
+ * width has to be calibrated.
38
+ */
39
+ export declare const STORE_HEADER_BYTES = 8;
40
+ /**
41
+ * V8 grows an elements store to `n + (n >> 1) + kMinAddedElementsCapacity`,
42
+ * with `kMinAddedElementsCapacity == 16`, so EVERY array built by `push`
43
+ * carries up to 16 slots of tail slack no application change can remove.
44
+ * Charging it turns a one-element array into a "94% empty" finding.
45
+ *
46
+ * https://github.com/v8/v8/blob/main/src/objects/js-objects.h
47
+ */
48
+ export declare const FORGIVEN_TAIL_SLOTS = 16;
49
+ export type SlotBytes = 4 | 8;
50
+ export interface ElementsInfo {
51
+ storeId: number;
52
+ storeBytes: number;
53
+ slotBytes: SlotBytes;
54
+ /** Slots the backing store is sized for. */
55
+ capacity: number;
56
+ /** Slots holding a value. LOWER BOUND — see fact 3 above. */
57
+ used: number;
58
+ maxIndex: number;
59
+ /** `maxIndex + 1` — how far into the store the written keys reach. */
60
+ span: number;
61
+ /** Interior holes: written keys are sparse within their own span. */
62
+ holes: number;
63
+ /** Raw tail slack past the last written key, before any forgiveness. */
64
+ slack: number;
65
+ mode: 'dense' | 'dictionary';
66
+ /**
67
+ * `false` when nothing readable is in the store — it may be all holes or all
68
+ * small integers, and a snapshot cannot tell those apart. Callers must not
69
+ * count these as waste.
70
+ */
71
+ measurable: boolean;
72
+ }
73
+ /** The raw two-sided read, before capacity is derived from a slot width. */
74
+ export interface RawElements {
75
+ store: IHeapNode;
76
+ /** Union occupancy: the owner's element edges are a superset of the store's. */
77
+ used: number;
78
+ maxIndex: number;
79
+ }
80
+ /** Read a node's elements store and its occupancy, or `null` if it has none. */
81
+ export declare function readRawElements(node: IHeapNode): RawElements | null;
82
+ /**
83
+ * Decide the slot width from evidence rather than assumption.
84
+ *
85
+ * A store whose largest written index fits in `(bytes - 8) / 4` slots but NOT
86
+ * in `(bytes - 8) / 8` can only be 4-byte-slotted. Dictionary-mode stores
87
+ * overflow both, so they cannot fake the signal. Pass any collection of
88
+ * observed `(storeBytes, maxIndex)` pairs; one witness is enough, and a real
89
+ * browser capture produces thousands.
90
+ */
91
+ export declare function calibrateSlotBytes(samples: Iterable<{
92
+ storeBytes: number;
93
+ maxIndex: number;
94
+ }>): SlotBytes;
95
+ /**
96
+ * Memoized per-snapshot slot width for tools that do not already make their own
97
+ * pass. Stops as soon as it has enough witnesses, so on a real heap it reads a
98
+ * small prefix rather than the whole graph.
99
+ */
100
+ export declare function getSlotBytes(snapshot: IHeapSnapshot): SlotBytes;
101
+ /** Derive the full picture from a raw read and a slot width. */
102
+ export declare function describeElements(raw: RawElements, slotBytes: SlotBytes): ElementsInfo | null;
103
+ /**
104
+ * Every node that owns an elements store, as parallel typed arrays.
105
+ *
106
+ * Built once per snapshot and memoized. Four tools ask the same structural
107
+ * questions of the same nodes (does this own an elements store? how many
108
+ * element edges? what is the largest index? how big is the store?), and each
109
+ * was paying its own full pass — on a 7.1M-node / 41.7M-edge capture that is
110
+ * the dominant cost of the call, and tuning one tool's parameters re-pays it
111
+ * every time.
112
+ *
113
+ * Typed arrays rather than objects: on the capture above this is ~370k entries,
114
+ * which is 6 MB as four typed arrays and several times that as objects. The
115
+ * index is keyed by the snapshot, so a `keep_previous` A/B keeps one per arm and
116
+ * both are released when the snapshot is.
117
+ */
118
+ export interface ElementsIndex {
119
+ /**
120
+ * Node ids that own an elements store, ascending by scan order.
121
+ *
122
+ * Unsigned: ids, byte counts and occupancies cannot be negative, and a
123
+ * signed 32-bit lane wraps anything past 2^31-1 to a negative number. For
124
+ * `ownerIds` that failure is silent rather than loud — `getNodeById(-…)`
125
+ * returns null, so the entry is skipped by every consumer instead of
126
+ * throwing. `maxIndex` stays signed because -1 is its "the store holds no
127
+ * numeric slot" sentinel, and a real element index above 2^31-1 would need a
128
+ * sparse array indexed past two billion.
129
+ *
130
+ * The unsigned lanes have their own ceiling at 2^32-1, and it is assumed
131
+ * rather than checked: V8 hands out snapshot node ids by increment, so
132
+ * exceeding it means one isolate allocated over four billion objects — far
133
+ * past the point where the snapshot itself is loadable here. A capture that
134
+ * did would truncate an id and quietly drop that entry, so if this ever needs
135
+ * to hold arbitrarily large captures, widen to `Float64Array` (ids stay exact
136
+ * to 2^53) rather than adding a guard.
137
+ */
138
+ ownerIds: Uint32Array;
139
+ storeBytes: Uint32Array;
140
+ used: Uint32Array;
141
+ maxIndex: Int32Array;
142
+ slotBytes: SlotBytes;
143
+ count: number;
144
+ }
145
+ export declare function getElementsIndex(snapshot: IHeapSnapshot): ElementsIndex;
146
+ /** One-shot read for a single node, calibrating the snapshot if needed. */
147
+ export declare function readElements(snapshot: IHeapSnapshot, node: IHeapNode): ElementsInfo | null;
148
+ //# sourceMappingURL=heap-shapes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heap-shapes.d.ts","sourceRoot":"","sources":["../src/heap-shapes.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAE,aAAa,EAAC,MAAM,cAAc,CAAC;AAE3D;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC;AAE9B,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,SAAS,CAAC;IACrB,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,GAAG,YAAY,CAAC;IAC7B;;;;OAIG;IACH,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,4EAA4E;AAC5E,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,SAAS,CAAC;IACjB,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,WAAW,GAAG,IAAI,CA4BnE;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,QAAQ,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,CAAC,GACxD,SAAS,CAWX;AAOD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,GAAG,SAAS,CA6B/D;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,WAAW,EAChB,SAAS,EAAE,SAAS,GACnB,YAAY,GAAG,IAAI,CAmBrB;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,EAAE,WAAW,CAAC;IACtB,UAAU,EAAE,WAAW,CAAC;IACxB,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,UAAU,CAAC;IACrB,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAID,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,aAAa,GAAG,aAAa,CA4CvE;AAED,2EAA2E;AAC3E,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,aAAa,EACvB,IAAI,EAAE,SAAS,GACd,YAAY,GAAG,IAAI,CAIrB"}
@@ -0,0 +1,193 @@
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
+ * Bytes of the FixedArray header preceding the first slot. Same on a
12
+ * pointer-compressed and an uncompressed heap (map + length), so only the slot
13
+ * width has to be calibrated.
14
+ */
15
+ export const STORE_HEADER_BYTES = 8;
16
+ /**
17
+ * V8 grows an elements store to `n + (n >> 1) + kMinAddedElementsCapacity`,
18
+ * with `kMinAddedElementsCapacity == 16`, so EVERY array built by `push`
19
+ * carries up to 16 slots of tail slack no application change can remove.
20
+ * Charging it turns a one-element array into a "94% empty" finding.
21
+ *
22
+ * https://github.com/v8/v8/blob/main/src/objects/js-objects.h
23
+ */
24
+ export const FORGIVEN_TAIL_SLOTS = 16;
25
+ /** Read a node's elements store and its occupancy, or `null` if it has none. */
26
+ export function readRawElements(node) {
27
+ let store = null;
28
+ let ownerSlots = 0;
29
+ let maxIndex = -1;
30
+ for (const edge of node.references) {
31
+ if (edge.type === 'element') {
32
+ ownerSlots++;
33
+ const index = Number(edge.name_or_index);
34
+ if (index > maxIndex)
35
+ maxIndex = index;
36
+ }
37
+ else if (edge.type === 'internal' &&
38
+ String(edge.name_or_index) === 'elements') {
39
+ store = edge.toNode;
40
+ }
41
+ }
42
+ if (!store)
43
+ return null;
44
+ let storeSlots = 0;
45
+ for (const edge of store.references) {
46
+ const name = String(edge.name_or_index);
47
+ // Numeric edge names on the store are slot indices; `map` and friends are
48
+ // header fields, not contents.
49
+ if (!/^\d+$/.test(name))
50
+ continue;
51
+ storeSlots++;
52
+ const index = Number(name);
53
+ if (index > maxIndex)
54
+ maxIndex = index;
55
+ }
56
+ return { store, used: Math.max(ownerSlots, storeSlots), maxIndex };
57
+ }
58
+ /**
59
+ * Decide the slot width from evidence rather than assumption.
60
+ *
61
+ * A store whose largest written index fits in `(bytes - 8) / 4` slots but NOT
62
+ * in `(bytes - 8) / 8` can only be 4-byte-slotted. Dictionary-mode stores
63
+ * overflow both, so they cannot fake the signal. Pass any collection of
64
+ * observed `(storeBytes, maxIndex)` pairs; one witness is enough, and a real
65
+ * browser capture produces thousands.
66
+ */
67
+ export function calibrateSlotBytes(samples) {
68
+ for (const s of samples) {
69
+ const slots = s.maxIndex + 1;
70
+ if (slots <= 0)
71
+ continue;
72
+ const at8 = (s.storeBytes - STORE_HEADER_BYTES) / 8;
73
+ const at4 = (s.storeBytes - STORE_HEADER_BYTES) / 4;
74
+ if (slots > at8 && slots <= at4)
75
+ return 4;
76
+ }
77
+ // Default to 4: every browser capture is pointer-compressed, and a heap with
78
+ // no witness either way is one where the difference changes no ranking.
79
+ return 4;
80
+ }
81
+ /** Witnesses needed before the scan stops early; more than enough to be sure. */
82
+ const CALIBRATION_WITNESSES = 32;
83
+ const slotBytesBySnapshot = new WeakMap();
84
+ /**
85
+ * Memoized per-snapshot slot width for tools that do not already make their own
86
+ * pass. Stops as soon as it has enough witnesses, so on a real heap it reads a
87
+ * small prefix rather than the whole graph.
88
+ */
89
+ export function getSlotBytes(snapshot) {
90
+ const cached = slotBytesBySnapshot.get(snapshot);
91
+ if (cached != null)
92
+ return cached;
93
+ const samples = [];
94
+ snapshot.nodes.forEach(node => {
95
+ // `false` is memlab's documented stop signal for this walk; a bare `return`
96
+ // only skips the current node, so returning undefined here kept iterating
97
+ // all 7M nodes of a large capture long after the 32nd witness. Every other
98
+ // `return` below is a per-node skip and must stay undefined.
99
+ if (samples.length >= CALIBRATION_WITNESSES)
100
+ return false;
101
+ if (node.type !== 'object' &&
102
+ node.type !== 'array' &&
103
+ node.type !== 'hidden')
104
+ return;
105
+ const raw = readRawElements(node);
106
+ if (!raw || raw.maxIndex < 0)
107
+ return;
108
+ const bytes = raw.store.self_size;
109
+ if (bytes <= STORE_HEADER_BYTES)
110
+ return;
111
+ const slots = raw.maxIndex + 1;
112
+ // Only witnesses that DISCRIMINATE are worth collecting.
113
+ if (slots > (bytes - STORE_HEADER_BYTES) / 8) {
114
+ samples.push({ storeBytes: bytes, maxIndex: raw.maxIndex });
115
+ }
116
+ });
117
+ const resolved = calibrateSlotBytes(samples);
118
+ slotBytesBySnapshot.set(snapshot, resolved);
119
+ return resolved;
120
+ }
121
+ /** Derive the full picture from a raw read and a slot width. */
122
+ export function describeElements(raw, slotBytes) {
123
+ const storeBytes = raw.store.self_size;
124
+ if (storeBytes <= STORE_HEADER_BYTES)
125
+ return null;
126
+ const capacity = Math.floor((storeBytes - STORE_HEADER_BYTES) / slotBytes);
127
+ const span = raw.maxIndex + 1;
128
+ const dictionary = span > capacity;
129
+ return {
130
+ storeId: raw.store.id,
131
+ storeBytes,
132
+ slotBytes,
133
+ capacity,
134
+ used: raw.used,
135
+ maxIndex: raw.maxIndex,
136
+ span,
137
+ holes: dictionary ? 0 : Math.max(0, span - raw.used),
138
+ slack: dictionary ? 0 : Math.max(0, capacity - span),
139
+ mode: dictionary ? 'dictionary' : 'dense',
140
+ measurable: raw.used > 0,
141
+ };
142
+ }
143
+ const elementsIndexBySnapshot = new WeakMap();
144
+ export function getElementsIndex(snapshot) {
145
+ const cached = elementsIndexBySnapshot.get(snapshot);
146
+ if (cached != null)
147
+ return cached;
148
+ const ownerIds = [];
149
+ const storeBytes = [];
150
+ const used = [];
151
+ const maxIndex = [];
152
+ snapshot.nodes.forEach(node => {
153
+ if (node.type !== 'object' &&
154
+ node.type !== 'array' &&
155
+ node.type !== 'hidden') {
156
+ return;
157
+ }
158
+ const raw = readRawElements(node);
159
+ if (!raw)
160
+ return;
161
+ const bytes = raw.store.self_size;
162
+ if (bytes <= STORE_HEADER_BYTES)
163
+ return;
164
+ ownerIds.push(node.id);
165
+ storeBytes.push(bytes);
166
+ used.push(raw.used);
167
+ maxIndex.push(raw.maxIndex);
168
+ });
169
+ const index = {
170
+ ownerIds: Uint32Array.from(ownerIds),
171
+ storeBytes: Uint32Array.from(storeBytes),
172
+ used: Uint32Array.from(used),
173
+ maxIndex: Int32Array.from(maxIndex),
174
+ // Calibrating from the entries just collected costs nothing extra and is
175
+ // strictly better evidence than the early-exit prefix scan.
176
+ slotBytes: calibrateSlotBytes(ownerIds.map((_, i) => ({
177
+ storeBytes: storeBytes[i],
178
+ maxIndex: maxIndex[i],
179
+ }))),
180
+ count: ownerIds.length,
181
+ };
182
+ elementsIndexBySnapshot.set(snapshot, index);
183
+ slotBytesBySnapshot.set(snapshot, index.slotBytes);
184
+ return index;
185
+ }
186
+ /** One-shot read for a single node, calibrating the snapshot if needed. */
187
+ export function readElements(snapshot, node) {
188
+ const raw = readRawElements(node);
189
+ if (!raw)
190
+ return null;
191
+ return describeElements(raw, getSlotBytes(snapshot));
192
+ }
193
+ //# sourceMappingURL=heap-shapes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heap-shapes.js","sourceRoot":"","sources":["../src/heap-shapes.ts"],"names":[],"mappings":"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"}