@flanksource/clicky-ui 0.3.22 → 0.3.24

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 (257) hide show
  1. package/dist/components/CountryFlag.cjs +55 -0
  2. package/dist/components/CountryFlag.cjs.map +1 -0
  3. package/dist/components/CountryFlag.d.ts +8 -0
  4. package/dist/components/CountryFlag.d.ts.map +1 -0
  5. package/dist/components/CountryFlag.js +38 -0
  6. package/dist/components/CountryFlag.js.map +1 -0
  7. package/dist/components/CountryPicker.cjs +35 -0
  8. package/dist/components/CountryPicker.cjs.map +1 -0
  9. package/dist/components/CountryPicker.d.ts +4 -0
  10. package/dist/components/CountryPicker.d.ts.map +1 -0
  11. package/dist/components/CountryPicker.js +35 -0
  12. package/dist/components/CountryPicker.js.map +1 -0
  13. package/dist/components/SplitButton.cjs +3 -2
  14. package/dist/components/SplitButton.cjs.map +1 -1
  15. package/dist/components/SplitButton.d.ts +6 -1
  16. package/dist/components/SplitButton.d.ts.map +1 -1
  17. package/dist/components/SplitButton.js +3 -2
  18. package/dist/components/SplitButton.js.map +1 -1
  19. package/dist/components/country-options.cjs +34 -0
  20. package/dist/components/country-options.cjs.map +1 -0
  21. package/dist/components/country-options.d.ts +8 -0
  22. package/dist/components/country-options.d.ts.map +1 -0
  23. package/dist/components/country-options.js +34 -0
  24. package/dist/components/country-options.js.map +1 -0
  25. package/dist/components.cjs +11 -0
  26. package/dist/components.cjs.map +1 -1
  27. package/dist/components.d.ts +4 -0
  28. package/dist/components.d.ts.map +1 -1
  29. package/dist/components.js +11 -0
  30. package/dist/components.js.map +1 -1
  31. package/dist/data/Clicky.cjs +4 -1
  32. package/dist/data/Clicky.cjs.map +1 -1
  33. package/dist/data/Clicky.d.ts.map +1 -1
  34. package/dist/data/Clicky.js +4 -1
  35. package/dist/data/Clicky.js.map +1 -1
  36. package/dist/data/CodeDiff.cjs +3 -18
  37. package/dist/data/CodeDiff.cjs.map +1 -1
  38. package/dist/data/CodeDiff.d.ts.map +1 -1
  39. package/dist/data/CodeDiff.js +3 -18
  40. package/dist/data/CodeDiff.js.map +1 -1
  41. package/dist/data/DataTable.cjs +182 -64
  42. package/dist/data/DataTable.cjs.map +1 -1
  43. package/dist/data/DataTable.d.ts +9 -1
  44. package/dist/data/DataTable.d.ts.map +1 -1
  45. package/dist/data/DataTable.grouping.cjs +26 -0
  46. package/dist/data/DataTable.grouping.cjs.map +1 -1
  47. package/dist/data/DataTable.grouping.d.ts +38 -0
  48. package/dist/data/DataTable.grouping.d.ts.map +1 -1
  49. package/dist/data/DataTable.grouping.js +26 -0
  50. package/dist/data/DataTable.grouping.js.map +1 -1
  51. package/dist/data/DataTable.js +183 -65
  52. package/dist/data/DataTable.js.map +1 -1
  53. package/dist/data/DataTableGroupingControls.cjs +84 -0
  54. package/dist/data/DataTableGroupingControls.cjs.map +1 -0
  55. package/dist/data/DataTableGroupingControls.d.ts +17 -0
  56. package/dist/data/DataTableGroupingControls.d.ts.map +1 -0
  57. package/dist/data/DataTableGroupingControls.js +84 -0
  58. package/dist/data/DataTableGroupingControls.js.map +1 -0
  59. package/dist/data/HighlightedTokens.cjs +21 -0
  60. package/dist/data/HighlightedTokens.cjs.map +1 -0
  61. package/dist/data/HighlightedTokens.d.ts +6 -0
  62. package/dist/data/HighlightedTokens.d.ts.map +1 -0
  63. package/dist/data/HighlightedTokens.js +21 -0
  64. package/dist/data/HighlightedTokens.js.map +1 -0
  65. package/dist/data/ai/AdvancedChatConfig.cjs +3 -0
  66. package/dist/data/ai/AdvancedChatConfig.cjs.map +1 -1
  67. package/dist/data/ai/AdvancedChatConfig.d.ts +2 -1
  68. package/dist/data/ai/AdvancedChatConfig.d.ts.map +1 -1
  69. package/dist/data/ai/AdvancedChatConfig.js +3 -0
  70. package/dist/data/ai/AdvancedChatConfig.js.map +1 -1
  71. package/dist/data/ai/ChatWindow.cjs +77 -4
  72. package/dist/data/ai/ChatWindow.cjs.map +1 -1
  73. package/dist/data/ai/ChatWindow.d.ts.map +1 -1
  74. package/dist/data/ai/ChatWindow.js +78 -5
  75. package/dist/data/ai/ChatWindow.js.map +1 -1
  76. package/dist/data/ai/ChatWindow.runtime.cjs +19 -4
  77. package/dist/data/ai/ChatWindow.runtime.cjs.map +1 -1
  78. package/dist/data/ai/ChatWindow.runtime.d.ts +2 -0
  79. package/dist/data/ai/ChatWindow.runtime.d.ts.map +1 -1
  80. package/dist/data/ai/ChatWindow.runtime.js +19 -4
  81. package/dist/data/ai/ChatWindow.runtime.js.map +1 -1
  82. package/dist/data/ai/ChatWindow.test-utils.d.ts +2 -1
  83. package/dist/data/ai/ChatWindow.test-utils.d.ts.map +1 -1
  84. package/dist/data/ai/ToolPreferences.cjs +8 -1
  85. package/dist/data/ai/ToolPreferences.cjs.map +1 -1
  86. package/dist/data/ai/ToolPreferences.d.ts +2 -1
  87. package/dist/data/ai/ToolPreferences.d.ts.map +1 -1
  88. package/dist/data/ai/ToolPreferences.js +8 -1
  89. package/dist/data/ai/ToolPreferences.js.map +1 -1
  90. package/dist/data/chat/Chat.cjs +26 -3
  91. package/dist/data/chat/Chat.cjs.map +1 -1
  92. package/dist/data/chat/Chat.d.ts +9 -1
  93. package/dist/data/chat/Chat.d.ts.map +1 -1
  94. package/dist/data/chat/Chat.js +26 -3
  95. package/dist/data/chat/Chat.js.map +1 -1
  96. package/dist/data/chat/ChatRuntimeToolbar.cjs +2 -0
  97. package/dist/data/chat/ChatRuntimeToolbar.cjs.map +1 -1
  98. package/dist/data/chat/ChatRuntimeToolbar.d.ts +2 -1
  99. package/dist/data/chat/ChatRuntimeToolbar.d.ts.map +1 -1
  100. package/dist/data/chat/ChatRuntimeToolbar.js +2 -0
  101. package/dist/data/chat/ChatRuntimeToolbar.js.map +1 -1
  102. package/dist/data/chat/Message.cjs +36 -1
  103. package/dist/data/chat/Message.cjs.map +1 -1
  104. package/dist/data/chat/Message.d.ts +1 -1
  105. package/dist/data/chat/Message.d.ts.map +1 -1
  106. package/dist/data/chat/Message.js +37 -2
  107. package/dist/data/chat/Message.js.map +1 -1
  108. package/dist/data/chat/approval.cjs +17 -0
  109. package/dist/data/chat/approval.cjs.map +1 -1
  110. package/dist/data/chat/approval.d.ts +5 -0
  111. package/dist/data/chat/approval.d.ts.map +1 -1
  112. package/dist/data/chat/approval.js +17 -0
  113. package/dist/data/chat/approval.js.map +1 -1
  114. package/dist/data/chat/fork-seed.cjs +22 -0
  115. package/dist/data/chat/fork-seed.cjs.map +1 -0
  116. package/dist/data/chat/fork-seed.d.ts +8 -0
  117. package/dist/data/chat/fork-seed.d.ts.map +1 -0
  118. package/dist/data/chat/fork-seed.js +22 -0
  119. package/dist/data/chat/fork-seed.js.map +1 -0
  120. package/dist/data/code-highlight.cjs +0 -6
  121. package/dist/data/code-highlight.cjs.map +1 -1
  122. package/dist/data/code-highlight.d.ts +4 -3
  123. package/dist/data/code-highlight.d.ts.map +1 -1
  124. package/dist/data/code-highlight.js +1 -7
  125. package/dist/data/code-highlight.js.map +1 -1
  126. package/dist/data/diagnostics/DiagnosticsDetailPanel.cjs +6 -2
  127. package/dist/data/diagnostics/DiagnosticsDetailPanel.cjs.map +1 -1
  128. package/dist/data/diagnostics/DiagnosticsDetailPanel.d.ts +8 -1
  129. package/dist/data/diagnostics/DiagnosticsDetailPanel.d.ts.map +1 -1
  130. package/dist/data/diagnostics/DiagnosticsDetailPanel.js +6 -2
  131. package/dist/data/diagnostics/DiagnosticsDetailPanel.js.map +1 -1
  132. package/dist/data/diagnostics/ErrorDetails.cjs +29 -5
  133. package/dist/data/diagnostics/ErrorDetails.cjs.map +1 -1
  134. package/dist/data/diagnostics/ErrorDetails.d.ts +3 -1
  135. package/dist/data/diagnostics/ErrorDetails.d.ts.map +1 -1
  136. package/dist/data/diagnostics/ErrorDetails.js +29 -5
  137. package/dist/data/diagnostics/ErrorDetails.js.map +1 -1
  138. package/dist/data/diagnostics/FrameSourceWindow.cjs +54 -24
  139. package/dist/data/diagnostics/FrameSourceWindow.cjs.map +1 -1
  140. package/dist/data/diagnostics/FrameSourceWindow.d.ts +2 -1
  141. package/dist/data/diagnostics/FrameSourceWindow.d.ts.map +1 -1
  142. package/dist/data/diagnostics/FrameSourceWindow.js +54 -24
  143. package/dist/data/diagnostics/FrameSourceWindow.js.map +1 -1
  144. package/dist/data/diagnostics/FrameSourceWindow.utils.cjs.map +1 -1
  145. package/dist/data/diagnostics/FrameSourceWindow.utils.d.ts +3 -0
  146. package/dist/data/diagnostics/FrameSourceWindow.utils.d.ts.map +1 -1
  147. package/dist/data/diagnostics/FrameSourceWindow.utils.js.map +1 -1
  148. package/dist/data/diagnostics/JvmStackTrace.cjs +14 -30
  149. package/dist/data/diagnostics/JvmStackTrace.cjs.map +1 -1
  150. package/dist/data/diagnostics/JvmStackTrace.d.ts +6 -9
  151. package/dist/data/diagnostics/JvmStackTrace.d.ts.map +1 -1
  152. package/dist/data/diagnostics/JvmStackTrace.js +15 -31
  153. package/dist/data/diagnostics/JvmStackTrace.js.map +1 -1
  154. package/dist/data/diagnostics/RenderedStackTrace.cjs +14 -144
  155. package/dist/data/diagnostics/RenderedStackTrace.cjs.map +1 -1
  156. package/dist/data/diagnostics/RenderedStackTrace.d.ts +6 -6
  157. package/dist/data/diagnostics/RenderedStackTrace.d.ts.map +1 -1
  158. package/dist/data/diagnostics/RenderedStackTrace.js +15 -145
  159. package/dist/data/diagnostics/RenderedStackTrace.js.map +1 -1
  160. package/dist/data/diagnostics/StackFrameRow.cjs +65 -0
  161. package/dist/data/diagnostics/StackFrameRow.cjs.map +1 -0
  162. package/dist/data/diagnostics/StackFrameRow.d.ts +13 -0
  163. package/dist/data/diagnostics/StackFrameRow.d.ts.map +1 -0
  164. package/dist/data/diagnostics/StackFrameRow.js +65 -0
  165. package/dist/data/diagnostics/StackFrameRow.js.map +1 -0
  166. package/dist/data/diagnostics/ThreadCard.cjs +9 -2
  167. package/dist/data/diagnostics/ThreadCard.cjs.map +1 -1
  168. package/dist/data/diagnostics/ThreadCard.d.ts +3 -1
  169. package/dist/data/diagnostics/ThreadCard.d.ts.map +1 -1
  170. package/dist/data/diagnostics/ThreadCard.js +9 -2
  171. package/dist/data/diagnostics/ThreadCard.js.map +1 -1
  172. package/dist/data/diagnostics/frame-heuristics.cjs +26 -0
  173. package/dist/data/diagnostics/frame-heuristics.cjs.map +1 -0
  174. package/dist/data/diagnostics/frame-heuristics.d.ts +5 -0
  175. package/dist/data/diagnostics/frame-heuristics.d.ts.map +1 -0
  176. package/dist/data/diagnostics/frame-heuristics.js +26 -0
  177. package/dist/data/diagnostics/frame-heuristics.js.map +1 -0
  178. package/dist/data/diagnostics/jvm-stacktrace.cjs +5 -7
  179. package/dist/data/diagnostics/jvm-stacktrace.cjs.map +1 -1
  180. package/dist/data/diagnostics/jvm-stacktrace.d.ts.map +1 -1
  181. package/dist/data/diagnostics/jvm-stacktrace.js +5 -7
  182. package/dist/data/diagnostics/jvm-stacktrace.js.map +1 -1
  183. package/dist/data/diagnostics/stacktrace-parse.cjs +4 -9
  184. package/dist/data/diagnostics/stacktrace-parse.cjs.map +1 -1
  185. package/dist/data/diagnostics/stacktrace-parse.d.ts.map +1 -1
  186. package/dist/data/diagnostics/stacktrace-parse.js +4 -9
  187. package/dist/data/diagnostics/stacktrace-parse.js.map +1 -1
  188. package/dist/data/runtime/RuntimeBar.cjs +3 -0
  189. package/dist/data/runtime/RuntimeBar.cjs.map +1 -1
  190. package/dist/data/runtime/RuntimeBar.d.ts +3 -1
  191. package/dist/data/runtime/RuntimeBar.d.ts.map +1 -1
  192. package/dist/data/runtime/RuntimeBar.js +3 -0
  193. package/dist/data/runtime/RuntimeBar.js.map +1 -1
  194. package/dist/data/runtime/RuntimeBarCombo.cjs +15 -1
  195. package/dist/data/runtime/RuntimeBarCombo.cjs.map +1 -1
  196. package/dist/data/runtime/RuntimeBarCombo.d.ts +2 -1
  197. package/dist/data/runtime/RuntimeBarCombo.d.ts.map +1 -1
  198. package/dist/data/runtime/RuntimeBarCombo.js +15 -1
  199. package/dist/data/runtime/RuntimeBarCombo.js.map +1 -1
  200. package/dist/data/runtime/RuntimeBarSegments.cjs +7 -0
  201. package/dist/data/runtime/RuntimeBarSegments.cjs.map +1 -1
  202. package/dist/data/runtime/RuntimeBarSegments.d.ts +2 -1
  203. package/dist/data/runtime/RuntimeBarSegments.d.ts.map +1 -1
  204. package/dist/data/runtime/RuntimeBarSegments.js +7 -0
  205. package/dist/data/runtime/RuntimeBarSegments.js.map +1 -1
  206. package/dist/data/version-info.cjs +3 -3
  207. package/dist/data/version-info.js +3 -3
  208. package/dist/data.cjs +7 -1
  209. package/dist/data.cjs.map +1 -1
  210. package/dist/data.d.ts +4 -2
  211. package/dist/data.d.ts.map +1 -1
  212. package/dist/data.js +8 -2
  213. package/dist/data.js.map +1 -1
  214. package/dist/index.cjs +18 -1
  215. package/dist/index.cjs.map +1 -1
  216. package/dist/index.js +19 -2
  217. package/dist/index.js.map +1 -1
  218. package/dist/rpc/CommandForm.cjs +8 -18
  219. package/dist/rpc/CommandForm.cjs.map +1 -1
  220. package/dist/rpc/CommandForm.d.ts +8 -2
  221. package/dist/rpc/CommandForm.d.ts.map +1 -1
  222. package/dist/rpc/CommandForm.js +9 -19
  223. package/dist/rpc/CommandForm.js.map +1 -1
  224. package/dist/rpc/OperationActionDialog.cjs +3 -3
  225. package/dist/rpc/OperationActionDialog.cjs.map +1 -1
  226. package/dist/rpc/OperationActionDialog.js +3 -3
  227. package/dist/rpc/OperationActionDialog.js.map +1 -1
  228. package/dist/rpc/OperationCommandPage.cjs +7 -7
  229. package/dist/rpc/OperationCommandPage.cjs.map +1 -1
  230. package/dist/rpc/OperationCommandPage.d.ts.map +1 -1
  231. package/dist/rpc/OperationCommandPage.js +7 -7
  232. package/dist/rpc/OperationCommandPage.js.map +1 -1
  233. package/dist/rpc/apiClient.cjs +17 -3
  234. package/dist/rpc/apiClient.cjs.map +1 -1
  235. package/dist/rpc/apiClient.d.ts +4 -4
  236. package/dist/rpc/apiClient.d.ts.map +1 -1
  237. package/dist/rpc/apiClient.js +17 -3
  238. package/dist/rpc/apiClient.js.map +1 -1
  239. package/dist/rpc/formMetadata.cjs +5 -9
  240. package/dist/rpc/formMetadata.cjs.map +1 -1
  241. package/dist/rpc/formMetadata.d.ts +3 -3
  242. package/dist/rpc/formMetadata.d.ts.map +1 -1
  243. package/dist/rpc/formMetadata.js +5 -9
  244. package/dist/rpc/formMetadata.js.map +1 -1
  245. package/dist/rpc/rpc-story.fixtures.d.ts.map +1 -1
  246. package/dist/rpc/types.cjs.map +1 -1
  247. package/dist/rpc/types.d.ts +1 -0
  248. package/dist/rpc/types.d.ts.map +1 -1
  249. package/dist/rpc/types.js.map +1 -1
  250. package/dist/rpc/useOperations.cjs.map +1 -1
  251. package/dist/rpc/useOperations.d.ts +4 -4
  252. package/dist/rpc/useOperations.d.ts.map +1 -1
  253. package/dist/rpc/useOperations.js.map +1 -1
  254. package/dist/rpc.d.ts +2 -2
  255. package/dist/rpc.d.ts.map +1 -1
  256. package/dist/styles.css +1 -1
  257. package/package.json +2 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StackFrameRow.cjs","sources":["../../../src/data/diagnostics/StackFrameRow.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { Icon } from \"../Icon\";\nimport {\n UiChip,\n UiDebugStepOver,\n UiLock,\n UiMethod,\n UiStackFrameDot,\n UiSync,\n UiWatch,\n} from \"../../icons\";\nimport { FrameSourceWindow } from \"./FrameSourceWindow\";\nimport { frameHasSource } from \"./FrameSourceWindow.utils\";\nimport type { ParsedThreadFrame } from \"./jvm-stacktrace\";\n\n// StackFrameActions renders trailing per-frame affordances. It is a slot: the\n// shared library never knows what the actions do, only where they go.\nexport type StackFrameActions = (frame: ParsedThreadFrame, index: number) => ReactNode;\n\nexport interface StackFrameRowProps {\n frame: ParsedThreadFrame;\n index: number;\n /** Show the 1-based frame ordinal in the gutter. */\n showIndex?: boolean;\n /** Trailing actions for this frame, revealed on hover/focus. */\n frameActions?: StackFrameActions;\n}\n\n// StackFrameRow is THE stack-frame renderer. Both an exception dump (via\n// StackTrace) and a JVM thread dump (via JvmStackTrace) render their frames\n// through it, so a frame looks and behaves the same wherever it is shown.\n//\n// Thread dumps carry lock/monitor annotation entries alongside real frames —\n// `frame.kind !== \"frame\"` — which are rendered as their own muted rows with a\n// lock/wait icon and no source window. An exception dump simply never produces\n// them.\nexport function StackFrameRow({\n frame,\n index,\n showIndex = false,\n frameActions,\n}: StackFrameRowProps) {\n const isAnnotation = frame.kind !== \"frame\";\n const methodName = frame.displayName || frame.method || frame.functionName;\n const actions = frameActions?.(frame, index);\n\n return (\n <div\n className={[\n \"group grid gap-2 px-3 py-1.5 text-xs\",\n showIndex ? \"grid-cols-[2rem_minmax(0,1fr)_auto]\" : \"grid-cols-[1.25rem_minmax(0,1fr)_auto]\",\n frame.runtime ? \"text-muted-foreground\" : \"text-foreground\",\n ].join(\" \")}\n >\n <div className=\"flex items-start justify-end gap-1 pt-0.5 font-mono text-[10px] text-muted-foreground\">\n {showIndex && <span>{index + 1}</span>}\n <Icon icon={frameIcon(frame)} className=\"mt-px shrink-0 text-[11px]\" />\n </div>\n\n <div className=\"min-w-0\">\n <div className=\"flex min-w-0 flex-wrap items-baseline gap-x-2 gap-y-0.5\">\n {isAnnotation ? (\n <>\n <span className=\"min-w-0 break-all font-mono font-semibold leading-4 opacity-70\">\n {frame.functionName}\n </span>\n {frame.annotationText && (\n <span className=\"min-w-0 break-all font-mono text-[11px] font-normal opacity-80\">\n {frame.annotationText}\n </span>\n )}\n </>\n ) : (\n <>\n <span className=\"min-w-0 break-all font-mono font-semibold leading-4\">\n {methodName}\n </span>\n {frame.class && (\n <span className=\"min-w-0 break-all font-mono text-[11px] text-muted-foreground\">\n {frame.class}\n </span>\n )}\n {frame.location && (\n <span className=\"rounded border border-border bg-muted/40 px-1.5 py-px font-mono text-[10px] text-muted-foreground\">\n {frame.location}\n </span>\n )}\n </>\n )}\n </div>\n </div>\n\n {actions ? (\n <div className=\"flex shrink-0 items-start gap-1 opacity-0 transition-opacity focus-within:opacity-100 group-hover:opacity-100\">\n {actions}\n </div>\n ) : (\n <div />\n )}\n\n {!isAnnotation && frameHasSource(frame) ? (\n <div className=\"col-span-3\">\n <FrameSourceWindow frame={frame} />\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction frameIcon(frame: ParsedThreadFrame) {\n switch (frame.kind) {\n case \"locked\":\n return UiLock;\n case \"waiting_to_lock\":\n return UiSync;\n case \"waiting_on\":\n case \"parking\":\n return UiWatch;\n default:\n break;\n }\n if (frame.nativeMethod) return UiChip;\n if (frame.runtime) return UiDebugStepOver;\n return frame.method || frame.class ? UiMethod : UiStackFrameDot;\n}\n"],"names":["jsxs","jsx","Icon","Fragment","frameHasSource","FrameSourceWindow","UiLock","UiSync","UiWatch","UiChip","UiDebugStepOver","UiMethod","UiStackFrameDot"],"mappings":";;;;;;;;;;;;;AAoCO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AACF,GAAuB;AACrB,QAAM,eAAe,MAAM,SAAS;AACpC,QAAM,aAAa,MAAM,eAAe,MAAM,UAAU,MAAM;AAC9D,QAAM,UAAU,6CAAe,OAAO;AAEtC,SACEA,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA,YAAY,wCAAwC;AAAA,QACpD,MAAM,UAAU,0BAA0B;AAAA,MAAA,EAC1C,KAAK,GAAG;AAAA,MAEV,UAAA;AAAA,QAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,yFACZ,UAAA;AAAA,UAAA,aAAaC,2BAAAA,IAAC,QAAA,EAAM,UAAA,QAAQ,GAAE;AAAA,yCAC9BC,KAAAA,MAAA,EAAK,MAAM,UAAU,KAAK,GAAG,WAAU,6BAAA,CAA6B;AAAA,QAAA,GACvE;AAAA,QAEAD,2BAAAA,IAAC,SAAI,WAAU,WACb,yCAAC,OAAA,EAAI,WAAU,2DACZ,UAAA,eACCD,2BAAAA,KAAAG,WAAAA,UAAA,EACE,UAAA;AAAA,UAAAF,2BAAAA,IAAC,QAAA,EAAK,WAAU,kEACb,UAAA,MAAM,cACT;AAAA,UACC,MAAM,kBACLA,2BAAAA,IAAC,UAAK,WAAU,kEACb,gBAAM,eAAA,CACT;AAAA,QAAA,EAAA,CAEJ,IAEAD,2BAAAA,KAAAG,WAAAA,UAAA,EACE,UAAA;AAAA,UAAAF,2BAAAA,IAAC,QAAA,EAAK,WAAU,uDACb,UAAA,YACH;AAAA,UACC,MAAM,SACLA,2BAAAA,IAAC,UAAK,WAAU,iEACb,gBAAM,OACT;AAAA,UAED,MAAM,YACLA,2BAAAA,IAAC,UAAK,WAAU,qGACb,gBAAM,SAAA,CACT;AAAA,QAAA,EAAA,CAEJ,GAEJ,GACF;AAAA,QAEC,yCACE,OAAA,EAAI,WAAU,iHACZ,UAAA,SACH,mCAEC,OAAA,CAAA,CAAI;AAAA,QAGN,CAAC,gBAAgBG,wBAAAA,eAAe,KAAK,IACpCH,2BAAAA,IAAC,OAAA,EAAI,WAAU,cACb,UAAAA,2BAAAA,IAACI,kBAAAA,mBAAA,EAAkB,MAAA,CAAc,GACnC,IACE;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGV;AAEA,SAAS,UAAU,OAA0B;AAC3C,UAAQ,MAAM,MAAA;AAAA,IACZ,KAAK;AACH,aAAOC,OAAAA;AAAAA,IACT,KAAK;AACH,aAAOC,OAAAA;AAAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAOC,QAAAA;AAAAA,EAEP;AAEJ,MAAI,MAAM,aAAc,QAAOC,OAAAA;AAC/B,MAAI,MAAM,QAAS,QAAOC,gBAAAA;AAC1B,SAAO,MAAM,UAAU,MAAM,QAAQC,SAAAA,WAAWC,gBAAAA;AAClD;;"}
@@ -0,0 +1,13 @@
1
+ import { ReactNode } from 'react';
2
+ import { ParsedThreadFrame } from './jvm-stacktrace';
3
+ export type StackFrameActions = (frame: ParsedThreadFrame, index: number) => ReactNode;
4
+ export interface StackFrameRowProps {
5
+ frame: ParsedThreadFrame;
6
+ index: number;
7
+ /** Show the 1-based frame ordinal in the gutter. */
8
+ showIndex?: boolean;
9
+ /** Trailing actions for this frame, revealed on hover/focus. */
10
+ frameActions?: StackFrameActions;
11
+ }
12
+ export declare function StackFrameRow({ frame, index, showIndex, frameActions, }: StackFrameRowProps): import("react/jsx-runtime").JSX.Element;
13
+ //# sourceMappingURL=StackFrameRow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StackFrameRow.d.ts","sourceRoot":"","sources":["../../../src/data/diagnostics/StackFrameRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAavC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAI1D,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC;AAEvF,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,iBAAiB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gEAAgE;IAChE,YAAY,CAAC,EAAE,iBAAiB,CAAC;CAClC;AAUD,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,KAAK,EACL,SAAiB,EACjB,YAAY,GACb,EAAE,kBAAkB,2CAkEpB"}
@@ -0,0 +1,65 @@
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
+ import { Icon } from "../Icon.js";
3
+ import { FrameSourceWindow } from "./FrameSourceWindow.js";
4
+ import { frameHasSource } from "./FrameSourceWindow.utils.js";
5
+ import { UiWatch } from "../../icons/components/UiWatch.js";
6
+ import { UiSync } from "../../icons/components/UiSync.js";
7
+ import { UiLock } from "../../icons/components/UiLock.js";
8
+ import { UiChip } from "../../icons/components/UiChip.js";
9
+ import { UiDebugStepOver } from "../../icons/components/UiDebugStepOver.js";
10
+ import { UiMethod } from "../../icons/components/UiMethod.js";
11
+ import { UiStackFrameDot } from "../../icons/components/UiStackFrameDot.js";
12
+ function StackFrameRow({
13
+ frame,
14
+ index,
15
+ showIndex = false,
16
+ frameActions
17
+ }) {
18
+ const isAnnotation = frame.kind !== "frame";
19
+ const methodName = frame.displayName || frame.method || frame.functionName;
20
+ const actions = frameActions == null ? void 0 : frameActions(frame, index);
21
+ return /* @__PURE__ */ jsxs(
22
+ "div",
23
+ {
24
+ className: [
25
+ "group grid gap-2 px-3 py-1.5 text-xs",
26
+ showIndex ? "grid-cols-[2rem_minmax(0,1fr)_auto]" : "grid-cols-[1.25rem_minmax(0,1fr)_auto]",
27
+ frame.runtime ? "text-muted-foreground" : "text-foreground"
28
+ ].join(" "),
29
+ children: [
30
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-end gap-1 pt-0.5 font-mono text-[10px] text-muted-foreground", children: [
31
+ showIndex && /* @__PURE__ */ jsx("span", { children: index + 1 }),
32
+ /* @__PURE__ */ jsx(Icon, { icon: frameIcon(frame), className: "mt-px shrink-0 text-[11px]" })
33
+ ] }),
34
+ /* @__PURE__ */ jsx("div", { className: "min-w-0", children: /* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-wrap items-baseline gap-x-2 gap-y-0.5", children: isAnnotation ? /* @__PURE__ */ jsxs(Fragment, { children: [
35
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 break-all font-mono font-semibold leading-4 opacity-70", children: frame.functionName }),
36
+ frame.annotationText && /* @__PURE__ */ jsx("span", { className: "min-w-0 break-all font-mono text-[11px] font-normal opacity-80", children: frame.annotationText })
37
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
38
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 break-all font-mono font-semibold leading-4", children: methodName }),
39
+ frame.class && /* @__PURE__ */ jsx("span", { className: "min-w-0 break-all font-mono text-[11px] text-muted-foreground", children: frame.class }),
40
+ frame.location && /* @__PURE__ */ jsx("span", { className: "rounded border border-border bg-muted/40 px-1.5 py-px font-mono text-[10px] text-muted-foreground", children: frame.location })
41
+ ] }) }) }),
42
+ actions ? /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-start gap-1 opacity-0 transition-opacity focus-within:opacity-100 group-hover:opacity-100", children: actions }) : /* @__PURE__ */ jsx("div", {}),
43
+ !isAnnotation && frameHasSource(frame) ? /* @__PURE__ */ jsx("div", { className: "col-span-3", children: /* @__PURE__ */ jsx(FrameSourceWindow, { frame }) }) : null
44
+ ]
45
+ }
46
+ );
47
+ }
48
+ function frameIcon(frame) {
49
+ switch (frame.kind) {
50
+ case "locked":
51
+ return UiLock;
52
+ case "waiting_to_lock":
53
+ return UiSync;
54
+ case "waiting_on":
55
+ case "parking":
56
+ return UiWatch;
57
+ }
58
+ if (frame.nativeMethod) return UiChip;
59
+ if (frame.runtime) return UiDebugStepOver;
60
+ return frame.method || frame.class ? UiMethod : UiStackFrameDot;
61
+ }
62
+ export {
63
+ StackFrameRow
64
+ };
65
+ //# sourceMappingURL=StackFrameRow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StackFrameRow.js","sources":["../../../src/data/diagnostics/StackFrameRow.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { Icon } from \"../Icon\";\nimport {\n UiChip,\n UiDebugStepOver,\n UiLock,\n UiMethod,\n UiStackFrameDot,\n UiSync,\n UiWatch,\n} from \"../../icons\";\nimport { FrameSourceWindow } from \"./FrameSourceWindow\";\nimport { frameHasSource } from \"./FrameSourceWindow.utils\";\nimport type { ParsedThreadFrame } from \"./jvm-stacktrace\";\n\n// StackFrameActions renders trailing per-frame affordances. It is a slot: the\n// shared library never knows what the actions do, only where they go.\nexport type StackFrameActions = (frame: ParsedThreadFrame, index: number) => ReactNode;\n\nexport interface StackFrameRowProps {\n frame: ParsedThreadFrame;\n index: number;\n /** Show the 1-based frame ordinal in the gutter. */\n showIndex?: boolean;\n /** Trailing actions for this frame, revealed on hover/focus. */\n frameActions?: StackFrameActions;\n}\n\n// StackFrameRow is THE stack-frame renderer. Both an exception dump (via\n// StackTrace) and a JVM thread dump (via JvmStackTrace) render their frames\n// through it, so a frame looks and behaves the same wherever it is shown.\n//\n// Thread dumps carry lock/monitor annotation entries alongside real frames —\n// `frame.kind !== \"frame\"` — which are rendered as their own muted rows with a\n// lock/wait icon and no source window. An exception dump simply never produces\n// them.\nexport function StackFrameRow({\n frame,\n index,\n showIndex = false,\n frameActions,\n}: StackFrameRowProps) {\n const isAnnotation = frame.kind !== \"frame\";\n const methodName = frame.displayName || frame.method || frame.functionName;\n const actions = frameActions?.(frame, index);\n\n return (\n <div\n className={[\n \"group grid gap-2 px-3 py-1.5 text-xs\",\n showIndex ? \"grid-cols-[2rem_minmax(0,1fr)_auto]\" : \"grid-cols-[1.25rem_minmax(0,1fr)_auto]\",\n frame.runtime ? \"text-muted-foreground\" : \"text-foreground\",\n ].join(\" \")}\n >\n <div className=\"flex items-start justify-end gap-1 pt-0.5 font-mono text-[10px] text-muted-foreground\">\n {showIndex && <span>{index + 1}</span>}\n <Icon icon={frameIcon(frame)} className=\"mt-px shrink-0 text-[11px]\" />\n </div>\n\n <div className=\"min-w-0\">\n <div className=\"flex min-w-0 flex-wrap items-baseline gap-x-2 gap-y-0.5\">\n {isAnnotation ? (\n <>\n <span className=\"min-w-0 break-all font-mono font-semibold leading-4 opacity-70\">\n {frame.functionName}\n </span>\n {frame.annotationText && (\n <span className=\"min-w-0 break-all font-mono text-[11px] font-normal opacity-80\">\n {frame.annotationText}\n </span>\n )}\n </>\n ) : (\n <>\n <span className=\"min-w-0 break-all font-mono font-semibold leading-4\">\n {methodName}\n </span>\n {frame.class && (\n <span className=\"min-w-0 break-all font-mono text-[11px] text-muted-foreground\">\n {frame.class}\n </span>\n )}\n {frame.location && (\n <span className=\"rounded border border-border bg-muted/40 px-1.5 py-px font-mono text-[10px] text-muted-foreground\">\n {frame.location}\n </span>\n )}\n </>\n )}\n </div>\n </div>\n\n {actions ? (\n <div className=\"flex shrink-0 items-start gap-1 opacity-0 transition-opacity focus-within:opacity-100 group-hover:opacity-100\">\n {actions}\n </div>\n ) : (\n <div />\n )}\n\n {!isAnnotation && frameHasSource(frame) ? (\n <div className=\"col-span-3\">\n <FrameSourceWindow frame={frame} />\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction frameIcon(frame: ParsedThreadFrame) {\n switch (frame.kind) {\n case \"locked\":\n return UiLock;\n case \"waiting_to_lock\":\n return UiSync;\n case \"waiting_on\":\n case \"parking\":\n return UiWatch;\n default:\n break;\n }\n if (frame.nativeMethod) return UiChip;\n if (frame.runtime) return UiDebugStepOver;\n return frame.method || frame.class ? UiMethod : UiStackFrameDot;\n}\n"],"names":[],"mappings":";;;;;;;;;;;AAoCO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AACF,GAAuB;AACrB,QAAM,eAAe,MAAM,SAAS;AACpC,QAAM,aAAa,MAAM,eAAe,MAAM,UAAU,MAAM;AAC9D,QAAM,UAAU,6CAAe,OAAO;AAEtC,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA,YAAY,wCAAwC;AAAA,QACpD,MAAM,UAAU,0BAA0B;AAAA,MAAA,EAC1C,KAAK,GAAG;AAAA,MAEV,UAAA;AAAA,QAAA,qBAAC,OAAA,EAAI,WAAU,yFACZ,UAAA;AAAA,UAAA,aAAa,oBAAC,QAAA,EAAM,UAAA,QAAQ,GAAE;AAAA,8BAC9B,MAAA,EAAK,MAAM,UAAU,KAAK,GAAG,WAAU,6BAAA,CAA6B;AAAA,QAAA,GACvE;AAAA,QAEA,oBAAC,SAAI,WAAU,WACb,8BAAC,OAAA,EAAI,WAAU,2DACZ,UAAA,eACC,qBAAA,UAAA,EACE,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAU,kEACb,UAAA,MAAM,cACT;AAAA,UACC,MAAM,kBACL,oBAAC,UAAK,WAAU,kEACb,gBAAM,eAAA,CACT;AAAA,QAAA,EAAA,CAEJ,IAEA,qBAAA,UAAA,EACE,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAU,uDACb,UAAA,YACH;AAAA,UACC,MAAM,SACL,oBAAC,UAAK,WAAU,iEACb,gBAAM,OACT;AAAA,UAED,MAAM,YACL,oBAAC,UAAK,WAAU,qGACb,gBAAM,SAAA,CACT;AAAA,QAAA,EAAA,CAEJ,GAEJ,GACF;AAAA,QAEC,8BACE,OAAA,EAAI,WAAU,iHACZ,UAAA,SACH,wBAEC,OAAA,CAAA,CAAI;AAAA,QAGN,CAAC,gBAAgB,eAAe,KAAK,IACpC,oBAAC,OAAA,EAAI,WAAU,cACb,UAAA,oBAAC,mBAAA,EAAkB,MAAA,CAAc,GACnC,IACE;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGV;AAEA,SAAS,UAAU,OAA0B;AAC3C,UAAQ,MAAM,MAAA;AAAA,IACZ,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,EAEP;AAEJ,MAAI,MAAM,aAAc,QAAO;AAC/B,MAAI,MAAM,QAAS,QAAO;AAC1B,SAAO,MAAM,UAAU,MAAM,QAAQ,WAAW;AAClD;"}
@@ -3,7 +3,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const JvmStackTrace = require("./JvmStackTrace.cjs");
5
5
  const stateStyles = require("./state-styles.cjs");
6
- function ThreadCard({ thread, search, hideRuntimeOnly, resolveSource }) {
6
+ function ThreadCard({
7
+ thread,
8
+ search,
9
+ hideRuntimeOnly,
10
+ resolveSource,
11
+ frameActions
12
+ }) {
7
13
  const frames = hideRuntimeOnly ? thread.frames.filter((f) => f.kind !== "frame" || !f.runtime) : thread.frames;
8
14
  const defaultOpen = thread.state === "runnable" || thread.state === "blocked" || !!search;
9
15
  return /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "border-0 bg-transparent", open: defaultOpen, children: [
@@ -41,7 +47,8 @@ function ThreadCard({ thread, search, hideRuntimeOnly, resolveSource }) {
41
47
  {
42
48
  frames,
43
49
  className: "space-y-0.5 py-1 pl-3",
44
- ...resolveSource ? { resolveSource } : {}
50
+ ...resolveSource ? { resolveSource } : {},
51
+ ...frameActions ? { frameActions } : {}
45
52
  }
46
53
  )
47
54
  ] });
@@ -1 +1 @@
1
- {"version":3,"file":"ThreadCard.cjs","sources":["../../../src/data/diagnostics/ThreadCard.tsx"],"sourcesContent":["import { JvmStackTrace, type JvmFrameSourceResolver } from \"./JvmStackTrace\";\nimport type { ParsedThread } from \"./jvm-stacktrace\";\nimport { threadStateBadge, threadStateDot } from \"./state-styles\";\n\nexport type ThreadCardProps = {\n thread: ParsedThread;\n search: string;\n hideRuntimeOnly: boolean;\n resolveSource?: JvmFrameSourceResolver;\n};\n\nexport function ThreadCard({ thread, search, hideRuntimeOnly, resolveSource }: ThreadCardProps) {\n const frames = hideRuntimeOnly\n ? thread.frames.filter((f) => f.kind !== \"frame\" || !f.runtime)\n : thread.frames;\n const defaultOpen = thread.state === \"runnable\" || thread.state === \"blocked\" || !!search;\n\n return (\n <details className=\"border-0 bg-transparent\" open={defaultOpen}>\n <summary className=\"cursor-pointer list-none px-0 py-1\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"font-mono text-xs font-semibold text-foreground\">#{thread.id}</span>\n <span className=\"truncate font-mono text-xs text-foreground\">{thread.name}</span>\n <span\n className={`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] ${threadStateBadge(\n thread.state,\n )}`}\n >\n <span className={`h-2 w-2 rounded-full ${threadStateDot(thread.state)}`} />\n {thread.rawState || thread.state}\n </span>\n {thread.daemon && (\n <span className=\"rounded-full bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground\">\n daemon\n </span>\n )}\n <span className=\"text-[11px] text-muted-foreground\">{frames.length}f</span>\n {thread.userFrameCount > 0 && (\n <span className=\"text-[11px] text-muted-foreground\">{thread.userFrameCount}u</span>\n )}\n {thread.topFunction && (\n <span className=\"truncate text-[11px] text-muted-foreground\">{thread.topFunction}</span>\n )}\n </div>\n </summary>\n <JvmStackTrace\n frames={frames}\n className=\"space-y-0.5 py-1 pl-3\"\n {...(resolveSource ? { resolveSource } : {})}\n />\n </details>\n );\n}\n"],"names":["jsxs","jsx","threadStateBadge","threadStateDot","JvmStackTrace"],"mappings":";;;;;AAWO,SAAS,WAAW,EAAE,QAAQ,QAAQ,iBAAiB,iBAAkC;AAC9F,QAAM,SAAS,kBACX,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,WAAW,CAAC,EAAE,OAAO,IAC5D,OAAO;AACX,QAAM,cAAc,OAAO,UAAU,cAAc,OAAO,UAAU,aAAa,CAAC,CAAC;AAEnF,SACEA,2BAAAA,KAAC,WAAA,EAAQ,WAAU,2BAA0B,MAAM,aACjD,UAAA;AAAA,IAAAC,2BAAAA,IAAC,aAAQ,WAAU,sCACjB,UAAAD,2BAAAA,KAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,MAAAA,2BAAAA,KAAC,QAAA,EAAK,WAAU,mDAAkD,UAAA;AAAA,QAAA;AAAA,QAAE,OAAO;AAAA,MAAA,GAAG;AAAA,MAC9EC,2BAAAA,IAAC,QAAA,EAAK,WAAU,8CAA8C,iBAAO,MAAK;AAAA,MAC1ED,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAW,uEAAuEE,YAAAA;AAAAA,YAChF,OAAO;AAAA,UAAA,CACR;AAAA,UAED,UAAA;AAAA,YAAAD,+BAAC,UAAK,WAAW,wBAAwBE,YAAAA,eAAe,OAAO,KAAK,CAAC,IAAI;AAAA,YACxE,OAAO,YAAY,OAAO;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAE5B,OAAO,UACNF,2BAAAA,IAAC,QAAA,EAAK,WAAU,yEAAwE,UAAA,UAExF;AAAA,MAEFD,2BAAAA,KAAC,QAAA,EAAK,WAAU,qCAAqC,UAAA;AAAA,QAAA,OAAO;AAAA,QAAO;AAAA,MAAA,GAAC;AAAA,MACnE,OAAO,iBAAiB,KACvBA,2BAAAA,KAAC,QAAA,EAAK,WAAU,qCAAqC,UAAA;AAAA,QAAA,OAAO;AAAA,QAAe;AAAA,MAAA,GAAC;AAAA,MAE7E,OAAO,eACNC,2BAAAA,IAAC,UAAK,WAAU,8CAA8C,iBAAO,YAAA,CAAY;AAAA,IAAA,EAAA,CAErF,EAAA,CACF;AAAA,IACAA,2BAAAA;AAAAA,MAACG,cAAAA;AAAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAU;AAAA,QACT,GAAI,gBAAgB,EAAE,kBAAkB,CAAA;AAAA,MAAC;AAAA,IAAA;AAAA,EAC5C,GACF;AAEJ;;"}
1
+ {"version":3,"file":"ThreadCard.cjs","sources":["../../../src/data/diagnostics/ThreadCard.tsx"],"sourcesContent":["import { JvmStackTrace, type JvmFrameSourceResolver } from \"./JvmStackTrace\";\nimport type { StackFrameActions } from \"./StackFrameRow\";\nimport type { ParsedThread } from \"./jvm-stacktrace\";\nimport { threadStateBadge, threadStateDot } from \"./state-styles\";\n\nexport type ThreadCardProps = {\n thread: ParsedThread;\n search: string;\n hideRuntimeOnly: boolean;\n resolveSource?: JvmFrameSourceResolver;\n frameActions?: StackFrameActions;\n};\n\nexport function ThreadCard({\n thread,\n search,\n hideRuntimeOnly,\n resolveSource,\n frameActions,\n}: ThreadCardProps) {\n const frames = hideRuntimeOnly\n ? thread.frames.filter((f) => f.kind !== \"frame\" || !f.runtime)\n : thread.frames;\n const defaultOpen = thread.state === \"runnable\" || thread.state === \"blocked\" || !!search;\n\n return (\n <details className=\"border-0 bg-transparent\" open={defaultOpen}>\n <summary className=\"cursor-pointer list-none px-0 py-1\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"font-mono text-xs font-semibold text-foreground\">#{thread.id}</span>\n <span className=\"truncate font-mono text-xs text-foreground\">{thread.name}</span>\n <span\n className={`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] ${threadStateBadge(\n thread.state,\n )}`}\n >\n <span className={`h-2 w-2 rounded-full ${threadStateDot(thread.state)}`} />\n {thread.rawState || thread.state}\n </span>\n {thread.daemon && (\n <span className=\"rounded-full bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground\">\n daemon\n </span>\n )}\n <span className=\"text-[11px] text-muted-foreground\">{frames.length}f</span>\n {thread.userFrameCount > 0 && (\n <span className=\"text-[11px] text-muted-foreground\">{thread.userFrameCount}u</span>\n )}\n {thread.topFunction && (\n <span className=\"truncate text-[11px] text-muted-foreground\">{thread.topFunction}</span>\n )}\n </div>\n </summary>\n <JvmStackTrace\n frames={frames}\n className=\"space-y-0.5 py-1 pl-3\"\n {...(resolveSource ? { resolveSource } : {})}\n {...(frameActions ? { frameActions } : {})}\n />\n </details>\n );\n}\n"],"names":["jsxs","jsx","threadStateBadge","threadStateDot","JvmStackTrace"],"mappings":";;;;;AAaO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoB;AAClB,QAAM,SAAS,kBACX,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,WAAW,CAAC,EAAE,OAAO,IAC5D,OAAO;AACX,QAAM,cAAc,OAAO,UAAU,cAAc,OAAO,UAAU,aAAa,CAAC,CAAC;AAEnF,SACEA,2BAAAA,KAAC,WAAA,EAAQ,WAAU,2BAA0B,MAAM,aACjD,UAAA;AAAA,IAAAC,2BAAAA,IAAC,aAAQ,WAAU,sCACjB,UAAAD,2BAAAA,KAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,MAAAA,2BAAAA,KAAC,QAAA,EAAK,WAAU,mDAAkD,UAAA;AAAA,QAAA;AAAA,QAAE,OAAO;AAAA,MAAA,GAAG;AAAA,MAC9EC,2BAAAA,IAAC,QAAA,EAAK,WAAU,8CAA8C,iBAAO,MAAK;AAAA,MAC1ED,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAW,uEAAuEE,YAAAA;AAAAA,YAChF,OAAO;AAAA,UAAA,CACR;AAAA,UAED,UAAA;AAAA,YAAAD,+BAAC,UAAK,WAAW,wBAAwBE,YAAAA,eAAe,OAAO,KAAK,CAAC,IAAI;AAAA,YACxE,OAAO,YAAY,OAAO;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAE5B,OAAO,UACNF,2BAAAA,IAAC,QAAA,EAAK,WAAU,yEAAwE,UAAA,UAExF;AAAA,MAEFD,2BAAAA,KAAC,QAAA,EAAK,WAAU,qCAAqC,UAAA;AAAA,QAAA,OAAO;AAAA,QAAO;AAAA,MAAA,GAAC;AAAA,MACnE,OAAO,iBAAiB,KACvBA,2BAAAA,KAAC,QAAA,EAAK,WAAU,qCAAqC,UAAA;AAAA,QAAA,OAAO;AAAA,QAAe;AAAA,MAAA,GAAC;AAAA,MAE7E,OAAO,eACNC,2BAAAA,IAAC,UAAK,WAAU,8CAA8C,iBAAO,YAAA,CAAY;AAAA,IAAA,EAAA,CAErF,EAAA,CACF;AAAA,IACAA,2BAAAA;AAAAA,MAACG,cAAAA;AAAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAU;AAAA,QACT,GAAI,gBAAgB,EAAE,cAAA,IAAkB,CAAA;AAAA,QACxC,GAAI,eAAe,EAAE,iBAAiB,CAAA;AAAA,MAAC;AAAA,IAAA;AAAA,EAC1C,GACF;AAEJ;;"}
@@ -1,10 +1,12 @@
1
1
  import { JvmFrameSourceResolver } from './JvmStackTrace';
2
+ import { StackFrameActions } from './StackFrameRow';
2
3
  import { ParsedThread } from './jvm-stacktrace';
3
4
  export type ThreadCardProps = {
4
5
  thread: ParsedThread;
5
6
  search: string;
6
7
  hideRuntimeOnly: boolean;
7
8
  resolveSource?: JvmFrameSourceResolver;
9
+ frameActions?: StackFrameActions;
8
10
  };
9
- export declare function ThreadCard({ thread, search, hideRuntimeOnly, resolveSource }: ThreadCardProps): import("react/jsx-runtime").JSX.Element;
11
+ export declare function ThreadCard({ thread, search, hideRuntimeOnly, resolveSource, frameActions, }: ThreadCardProps): import("react/jsx-runtime").JSX.Element;
10
12
  //# sourceMappingURL=ThreadCard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ThreadCard.d.ts","sourceRoot":"","sources":["../../../src/data/diagnostics/ThreadCard.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGrD,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,sBAAsB,CAAC;CACxC,CAAC;AAEF,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,aAAa,EAAE,EAAE,eAAe,2CAyC7F"}
1
+ {"version":3,"file":"ThreadCard.d.ts","sourceRoot":"","sources":["../../../src/data/diagnostics/ThreadCard.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAC7E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGrD,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,sBAAsB,CAAC;IACvC,YAAY,CAAC,EAAE,iBAAiB,CAAC;CAClC,CAAC;AAEF,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,MAAM,EACN,eAAe,EACf,aAAa,EACb,YAAY,GACb,EAAE,eAAe,2CA0CjB"}
@@ -1,7 +1,13 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { JvmStackTrace } from "./JvmStackTrace.js";
3
3
  import { threadStateDot, threadStateBadge } from "./state-styles.js";
4
- function ThreadCard({ thread, search, hideRuntimeOnly, resolveSource }) {
4
+ function ThreadCard({
5
+ thread,
6
+ search,
7
+ hideRuntimeOnly,
8
+ resolveSource,
9
+ frameActions
10
+ }) {
5
11
  const frames = hideRuntimeOnly ? thread.frames.filter((f) => f.kind !== "frame" || !f.runtime) : thread.frames;
6
12
  const defaultOpen = thread.state === "runnable" || thread.state === "blocked" || !!search;
7
13
  return /* @__PURE__ */ jsxs("details", { className: "border-0 bg-transparent", open: defaultOpen, children: [
@@ -39,7 +45,8 @@ function ThreadCard({ thread, search, hideRuntimeOnly, resolveSource }) {
39
45
  {
40
46
  frames,
41
47
  className: "space-y-0.5 py-1 pl-3",
42
- ...resolveSource ? { resolveSource } : {}
48
+ ...resolveSource ? { resolveSource } : {},
49
+ ...frameActions ? { frameActions } : {}
43
50
  }
44
51
  )
45
52
  ] });
@@ -1 +1 @@
1
- {"version":3,"file":"ThreadCard.js","sources":["../../../src/data/diagnostics/ThreadCard.tsx"],"sourcesContent":["import { JvmStackTrace, type JvmFrameSourceResolver } from \"./JvmStackTrace\";\nimport type { ParsedThread } from \"./jvm-stacktrace\";\nimport { threadStateBadge, threadStateDot } from \"./state-styles\";\n\nexport type ThreadCardProps = {\n thread: ParsedThread;\n search: string;\n hideRuntimeOnly: boolean;\n resolveSource?: JvmFrameSourceResolver;\n};\n\nexport function ThreadCard({ thread, search, hideRuntimeOnly, resolveSource }: ThreadCardProps) {\n const frames = hideRuntimeOnly\n ? thread.frames.filter((f) => f.kind !== \"frame\" || !f.runtime)\n : thread.frames;\n const defaultOpen = thread.state === \"runnable\" || thread.state === \"blocked\" || !!search;\n\n return (\n <details className=\"border-0 bg-transparent\" open={defaultOpen}>\n <summary className=\"cursor-pointer list-none px-0 py-1\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"font-mono text-xs font-semibold text-foreground\">#{thread.id}</span>\n <span className=\"truncate font-mono text-xs text-foreground\">{thread.name}</span>\n <span\n className={`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] ${threadStateBadge(\n thread.state,\n )}`}\n >\n <span className={`h-2 w-2 rounded-full ${threadStateDot(thread.state)}`} />\n {thread.rawState || thread.state}\n </span>\n {thread.daemon && (\n <span className=\"rounded-full bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground\">\n daemon\n </span>\n )}\n <span className=\"text-[11px] text-muted-foreground\">{frames.length}f</span>\n {thread.userFrameCount > 0 && (\n <span className=\"text-[11px] text-muted-foreground\">{thread.userFrameCount}u</span>\n )}\n {thread.topFunction && (\n <span className=\"truncate text-[11px] text-muted-foreground\">{thread.topFunction}</span>\n )}\n </div>\n </summary>\n <JvmStackTrace\n frames={frames}\n className=\"space-y-0.5 py-1 pl-3\"\n {...(resolveSource ? { resolveSource } : {})}\n />\n </details>\n );\n}\n"],"names":[],"mappings":";;;AAWO,SAAS,WAAW,EAAE,QAAQ,QAAQ,iBAAiB,iBAAkC;AAC9F,QAAM,SAAS,kBACX,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,WAAW,CAAC,EAAE,OAAO,IAC5D,OAAO;AACX,QAAM,cAAc,OAAO,UAAU,cAAc,OAAO,UAAU,aAAa,CAAC,CAAC;AAEnF,SACE,qBAAC,WAAA,EAAQ,WAAU,2BAA0B,MAAM,aACjD,UAAA;AAAA,IAAA,oBAAC,aAAQ,WAAU,sCACjB,UAAA,qBAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,MAAA,qBAAC,QAAA,EAAK,WAAU,mDAAkD,UAAA;AAAA,QAAA;AAAA,QAAE,OAAO;AAAA,MAAA,GAAG;AAAA,MAC9E,oBAAC,QAAA,EAAK,WAAU,8CAA8C,iBAAO,MAAK;AAAA,MAC1E;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAW,uEAAuE;AAAA,YAChF,OAAO;AAAA,UAAA,CACR;AAAA,UAED,UAAA;AAAA,YAAA,oBAAC,UAAK,WAAW,wBAAwB,eAAe,OAAO,KAAK,CAAC,IAAI;AAAA,YACxE,OAAO,YAAY,OAAO;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAE5B,OAAO,UACN,oBAAC,QAAA,EAAK,WAAU,yEAAwE,UAAA,UAExF;AAAA,MAEF,qBAAC,QAAA,EAAK,WAAU,qCAAqC,UAAA;AAAA,QAAA,OAAO;AAAA,QAAO;AAAA,MAAA,GAAC;AAAA,MACnE,OAAO,iBAAiB,KACvB,qBAAC,QAAA,EAAK,WAAU,qCAAqC,UAAA;AAAA,QAAA,OAAO;AAAA,QAAe;AAAA,MAAA,GAAC;AAAA,MAE7E,OAAO,eACN,oBAAC,UAAK,WAAU,8CAA8C,iBAAO,YAAA,CAAY;AAAA,IAAA,EAAA,CAErF,EAAA,CACF;AAAA,IACA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAU;AAAA,QACT,GAAI,gBAAgB,EAAE,kBAAkB,CAAA;AAAA,MAAC;AAAA,IAAA;AAAA,EAC5C,GACF;AAEJ;"}
1
+ {"version":3,"file":"ThreadCard.js","sources":["../../../src/data/diagnostics/ThreadCard.tsx"],"sourcesContent":["import { JvmStackTrace, type JvmFrameSourceResolver } from \"./JvmStackTrace\";\nimport type { StackFrameActions } from \"./StackFrameRow\";\nimport type { ParsedThread } from \"./jvm-stacktrace\";\nimport { threadStateBadge, threadStateDot } from \"./state-styles\";\n\nexport type ThreadCardProps = {\n thread: ParsedThread;\n search: string;\n hideRuntimeOnly: boolean;\n resolveSource?: JvmFrameSourceResolver;\n frameActions?: StackFrameActions;\n};\n\nexport function ThreadCard({\n thread,\n search,\n hideRuntimeOnly,\n resolveSource,\n frameActions,\n}: ThreadCardProps) {\n const frames = hideRuntimeOnly\n ? thread.frames.filter((f) => f.kind !== \"frame\" || !f.runtime)\n : thread.frames;\n const defaultOpen = thread.state === \"runnable\" || thread.state === \"blocked\" || !!search;\n\n return (\n <details className=\"border-0 bg-transparent\" open={defaultOpen}>\n <summary className=\"cursor-pointer list-none px-0 py-1\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"font-mono text-xs font-semibold text-foreground\">#{thread.id}</span>\n <span className=\"truncate font-mono text-xs text-foreground\">{thread.name}</span>\n <span\n className={`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] ${threadStateBadge(\n thread.state,\n )}`}\n >\n <span className={`h-2 w-2 rounded-full ${threadStateDot(thread.state)}`} />\n {thread.rawState || thread.state}\n </span>\n {thread.daemon && (\n <span className=\"rounded-full bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground\">\n daemon\n </span>\n )}\n <span className=\"text-[11px] text-muted-foreground\">{frames.length}f</span>\n {thread.userFrameCount > 0 && (\n <span className=\"text-[11px] text-muted-foreground\">{thread.userFrameCount}u</span>\n )}\n {thread.topFunction && (\n <span className=\"truncate text-[11px] text-muted-foreground\">{thread.topFunction}</span>\n )}\n </div>\n </summary>\n <JvmStackTrace\n frames={frames}\n className=\"space-y-0.5 py-1 pl-3\"\n {...(resolveSource ? { resolveSource } : {})}\n {...(frameActions ? { frameActions } : {})}\n />\n </details>\n );\n}\n"],"names":[],"mappings":";;;AAaO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoB;AAClB,QAAM,SAAS,kBACX,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,WAAW,CAAC,EAAE,OAAO,IAC5D,OAAO;AACX,QAAM,cAAc,OAAO,UAAU,cAAc,OAAO,UAAU,aAAa,CAAC,CAAC;AAEnF,SACE,qBAAC,WAAA,EAAQ,WAAU,2BAA0B,MAAM,aACjD,UAAA;AAAA,IAAA,oBAAC,aAAQ,WAAU,sCACjB,UAAA,qBAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,MAAA,qBAAC,QAAA,EAAK,WAAU,mDAAkD,UAAA;AAAA,QAAA;AAAA,QAAE,OAAO;AAAA,MAAA,GAAG;AAAA,MAC9E,oBAAC,QAAA,EAAK,WAAU,8CAA8C,iBAAO,MAAK;AAAA,MAC1E;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAW,uEAAuE;AAAA,YAChF,OAAO;AAAA,UAAA,CACR;AAAA,UAED,UAAA;AAAA,YAAA,oBAAC,UAAK,WAAW,wBAAwB,eAAe,OAAO,KAAK,CAAC,IAAI;AAAA,YACxE,OAAO,YAAY,OAAO;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAE5B,OAAO,UACN,oBAAC,QAAA,EAAK,WAAU,yEAAwE,UAAA,UAExF;AAAA,MAEF,qBAAC,QAAA,EAAK,WAAU,qCAAqC,UAAA;AAAA,QAAA,OAAO;AAAA,QAAO;AAAA,MAAA,GAAC;AAAA,MACnE,OAAO,iBAAiB,KACvB,qBAAC,QAAA,EAAK,WAAU,qCAAqC,UAAA;AAAA,QAAA,OAAO;AAAA,QAAe;AAAA,MAAA,GAAC;AAAA,MAE7E,OAAO,eACN,oBAAC,UAAK,WAAU,8CAA8C,iBAAO,YAAA,CAAY;AAAA,IAAA,EAAA,CAErF,EAAA,CACF;AAAA,IACA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAU;AAAA,QACT,GAAI,gBAAgB,EAAE,cAAA,IAAkB,CAAA;AAAA,QACxC,GAAI,eAAe,EAAE,iBAAiB,CAAA;AAAA,MAAC;AAAA,IAAA;AAAA,EAC1C,GACF;AAEJ;"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const RUNTIME_PREFIXES = [
4
+ "java.",
5
+ "javax.",
6
+ "sun.",
7
+ "jdk.",
8
+ "com.sun.",
9
+ "oracle.jrockit."
10
+ ];
11
+ function isRuntimeFrame(className, extraPrefixes = []) {
12
+ return RUNTIME_PREFIXES.some((p) => className.startsWith(p)) || extraPrefixes.some((p) => className.startsWith(p));
13
+ }
14
+ function shortFrameName(className, method) {
15
+ const last = className.split(".").filter(Boolean).pop() ?? className;
16
+ return [last, method].filter(Boolean).join(".");
17
+ }
18
+ function frameLocation(file, line) {
19
+ if (!file) return void 0;
20
+ return line === void 0 ? file : `${file}:${line}`;
21
+ }
22
+ exports.RUNTIME_PREFIXES = RUNTIME_PREFIXES;
23
+ exports.frameLocation = frameLocation;
24
+ exports.isRuntimeFrame = isRuntimeFrame;
25
+ exports.shortFrameName = shortFrameName;
26
+ //# sourceMappingURL=frame-heuristics.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-heuristics.cjs","sources":["../../../src/data/diagnostics/frame-heuristics.ts"],"sourcesContent":["// Shared frame heuristics for the JVM diagnostics renderers. Both parsers — the\n// exception-dump parser (stacktrace-parse) and the thread-dump parser\n// (jvm-stacktrace) — classify and label frames the same way, so the rules live\n// here rather than being restated in each.\n\n// Packages that are JVM/JDK internals rather than application code. Frames\n// matching one are marked `runtime`, which mutes them and lets a renderer drop\n// them via `hideRuntimeOnly`.\n//\n// Deliberately conservative: it covers the JDK only. A consumer whose noise\n// floor is higher (a servlet container's frames, a profiling agent's own\n// frames) passes its extra prefixes to `isRuntimeFrame` rather than forking\n// this list — what counts as noise is the consumer's call, not ours.\nexport const RUNTIME_PREFIXES = [\n \"java.\",\n \"javax.\",\n \"sun.\",\n \"jdk.\",\n \"com.sun.\",\n \"or\" + \"acle.jrockit.\",\n];\n\nexport function isRuntimeFrame(className: string, extraPrefixes: string[] = []): boolean {\n return (\n RUNTIME_PREFIXES.some((p) => className.startsWith(p)) ||\n extraPrefixes.some((p) => className.startsWith(p))\n );\n}\n\n// shortFrameName collapses a fully-qualified frame to `Class.method` for\n// display, keeping any inner-class suffix: `com.example.App$Inner.run` →\n// `App$Inner.run`. Returns the input unchanged when it has no package.\nexport function shortFrameName(className: string, method: string): string {\n const last = className.split(\".\").filter(Boolean).pop() ?? className;\n return [last, method].filter(Boolean).join(\".\");\n}\n\n// frameLocation renders the `File.java:42` badge, degrading to the bare file\n// when no line was captured and to undefined when there is no file at all.\n// Line 0 is a captured location, not an absent one, so the check is against\n// undefined rather than falsiness.\nexport function frameLocation(file?: string, line?: number): string | undefined {\n if (!file) return undefined;\n return line === undefined ? file : `${file}:${line}`;\n}\n"],"names":[],"mappings":";;AAaO,MAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,eAAe,WAAmB,gBAA0B,IAAa;AACvF,SACE,iBAAiB,KAAK,CAAC,MAAM,UAAU,WAAW,CAAC,CAAC,KACpD,cAAc,KAAK,CAAC,MAAM,UAAU,WAAW,CAAC,CAAC;AAErD;AAKO,SAAS,eAAe,WAAmB,QAAwB;AACxE,QAAM,OAAO,UAAU,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,IAAA,KAAS;AAC3D,SAAO,CAAC,MAAM,MAAM,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAChD;AAMO,SAAS,cAAc,MAAe,MAAmC;AAC9E,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,SAAS,SAAY,OAAO,GAAG,IAAI,IAAI,IAAI;AACpD;;;;;"}
@@ -0,0 +1,5 @@
1
+ export declare const RUNTIME_PREFIXES: string[];
2
+ export declare function isRuntimeFrame(className: string, extraPrefixes?: string[]): boolean;
3
+ export declare function shortFrameName(className: string, method: string): string;
4
+ export declare function frameLocation(file?: string, line?: number): string | undefined;
5
+ //# sourceMappingURL=frame-heuristics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-heuristics.d.ts","sourceRoot":"","sources":["../../../src/data/diagnostics/frame-heuristics.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,gBAAgB,UAO5B,CAAC;AAEF,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,GAAE,MAAM,EAAO,GAAG,OAAO,CAKvF;AAKD,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGxE;AAMD,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG9E"}
@@ -0,0 +1,26 @@
1
+ const RUNTIME_PREFIXES = [
2
+ "java.",
3
+ "javax.",
4
+ "sun.",
5
+ "jdk.",
6
+ "com.sun.",
7
+ "oracle.jrockit."
8
+ ];
9
+ function isRuntimeFrame(className, extraPrefixes = []) {
10
+ return RUNTIME_PREFIXES.some((p) => className.startsWith(p)) || extraPrefixes.some((p) => className.startsWith(p));
11
+ }
12
+ function shortFrameName(className, method) {
13
+ const last = className.split(".").filter(Boolean).pop() ?? className;
14
+ return [last, method].filter(Boolean).join(".");
15
+ }
16
+ function frameLocation(file, line) {
17
+ if (!file) return void 0;
18
+ return line === void 0 ? file : `${file}:${line}`;
19
+ }
20
+ export {
21
+ RUNTIME_PREFIXES,
22
+ frameLocation,
23
+ isRuntimeFrame,
24
+ shortFrameName
25
+ };
26
+ //# sourceMappingURL=frame-heuristics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-heuristics.js","sources":["../../../src/data/diagnostics/frame-heuristics.ts"],"sourcesContent":["// Shared frame heuristics for the JVM diagnostics renderers. Both parsers — the\n// exception-dump parser (stacktrace-parse) and the thread-dump parser\n// (jvm-stacktrace) — classify and label frames the same way, so the rules live\n// here rather than being restated in each.\n\n// Packages that are JVM/JDK internals rather than application code. Frames\n// matching one are marked `runtime`, which mutes them and lets a renderer drop\n// them via `hideRuntimeOnly`.\n//\n// Deliberately conservative: it covers the JDK only. A consumer whose noise\n// floor is higher (a servlet container's frames, a profiling agent's own\n// frames) passes its extra prefixes to `isRuntimeFrame` rather than forking\n// this list — what counts as noise is the consumer's call, not ours.\nexport const RUNTIME_PREFIXES = [\n \"java.\",\n \"javax.\",\n \"sun.\",\n \"jdk.\",\n \"com.sun.\",\n \"or\" + \"acle.jrockit.\",\n];\n\nexport function isRuntimeFrame(className: string, extraPrefixes: string[] = []): boolean {\n return (\n RUNTIME_PREFIXES.some((p) => className.startsWith(p)) ||\n extraPrefixes.some((p) => className.startsWith(p))\n );\n}\n\n// shortFrameName collapses a fully-qualified frame to `Class.method` for\n// display, keeping any inner-class suffix: `com.example.App$Inner.run` →\n// `App$Inner.run`. Returns the input unchanged when it has no package.\nexport function shortFrameName(className: string, method: string): string {\n const last = className.split(\".\").filter(Boolean).pop() ?? className;\n return [last, method].filter(Boolean).join(\".\");\n}\n\n// frameLocation renders the `File.java:42` badge, degrading to the bare file\n// when no line was captured and to undefined when there is no file at all.\n// Line 0 is a captured location, not an absent one, so the check is against\n// undefined rather than falsiness.\nexport function frameLocation(file?: string, line?: number): string | undefined {\n if (!file) return undefined;\n return line === undefined ? file : `${file}:${line}`;\n}\n"],"names":[],"mappings":"AAaO,MAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,eAAe,WAAmB,gBAA0B,IAAa;AACvF,SACE,iBAAiB,KAAK,CAAC,MAAM,UAAU,WAAW,CAAC,CAAC,KACpD,cAAc,KAAK,CAAC,MAAM,UAAU,WAAW,CAAC,CAAC;AAErD;AAKO,SAAS,eAAe,WAAmB,QAAwB;AACxE,QAAM,OAAO,UAAU,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,IAAA,KAAS;AAC3D,SAAO,CAAC,MAAM,MAAM,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAChD;AAMO,SAAS,cAAc,MAAe,MAAmC;AAC9E,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,SAAS,SAAY,OAAO,GAAG,IAAI,IAAI,IAAI;AACpD;"}
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const frameHeuristics = require("./frame-heuristics.cjs");
3
4
  const headerRe = /^"(?<name>[^"]*)"(?<rest>.*)$/;
4
5
  const stateRe = /^\s*java\.lang\.Thread\.State:\s+(?<state>[A-Z_]+)(?:\s+\((?<sub>[^)]+)\))?/;
5
6
  const frameRe = /^\s*at\s+(?<fn>[^\s(]+)\((?<src>[^)]+)\)\s*$/;
@@ -207,9 +208,8 @@ function normalizeJvmState(value) {
207
208
  if (lower.includes("blocked")) return "blocked";
208
209
  return lower.split(/\s+/)[0] ?? "";
209
210
  }
210
- const runtimePrefixes = ["java.", "javax.", "sun.", "jdk.", "com.sun.", "oracle.jrockit."];
211
211
  function isJvmRuntimeFrame(functionName) {
212
- return runtimePrefixes.some((p) => functionName.startsWith(p));
212
+ return frameHeuristics.isRuntimeFrame(functionName);
213
213
  }
214
214
  function splitClassMethod(functionName) {
215
215
  const lastDot = functionName.lastIndexOf(".");
@@ -220,11 +220,9 @@ function splitClassMethod(functionName) {
220
220
  };
221
221
  }
222
222
  function sanitizeJvmFunctionName(functionName) {
223
- const parts = functionName.split(".");
224
- if (parts.length < 2) return functionName;
225
- const method = parts[parts.length - 1];
226
- const cls = parts[parts.length - 2];
227
- return `${cls}.${method}`;
223
+ const lastDot = functionName.lastIndexOf(".");
224
+ if (lastDot <= 0) return functionName;
225
+ return frameHeuristics.shortFrameName(functionName.slice(0, lastDot), functionName.slice(lastDot + 1));
228
226
  }
229
227
  exports.countThreadsByState = countThreadsByState;
230
228
  exports.parseJvmThreadDump = parseJvmThreadDump;
@@ -1 +1 @@
1
- {"version":3,"file":"jvm-stacktrace.cjs","sources":["../../../src/data/diagnostics/jvm-stacktrace.ts"],"sourcesContent":["export interface ParsedThreadFrame {\n functionName: string;\n displayName: string;\n file?: string;\n line?: number;\n location?: string;\n kind: \"frame\" | \"locked\" | \"waiting_on\" | \"waiting_to_lock\" | \"parking\";\n runtime: boolean;\n nativeMethod: boolean;\n annotationText?: string;\n // Optional fully-qualified class name (e.g. \"com.example.admin.pas.Foo\").\n // Lets renderers filter or group by package without re-splitting\n // functionName. Populated by parseJavaStackTrace; left undefined by the\n // thread-dump parser since its frames are raw \"fn(src)\" pairs.\n class?: string;\n method?: string;\n // Optional source-context window populated by clicky.SourceResolver\n // (or its TS equivalent). sourceLines[line - sourceStartLine] is the focal\n // line. Empty/undefined when no resolver was attached.\n sourceLines?: string[];\n sourceLineNumbers?: number[];\n sourceStartLine?: number;\n sourceLanguage?: string;\n}\n\nexport interface ParsedThread {\n id: number;\n nid?: string;\n name: string;\n state: string;\n rawState: string;\n priority?: number;\n daemon?: boolean;\n frames: ParsedThreadFrame[];\n raw: string;\n userFrameCount: number;\n topFunction?: string;\n searchText: string;\n}\n\nconst headerRe = /^\"(?<name>[^\"]*)\"(?<rest>.*)$/;\nconst stateRe = /^\\s*java\\.lang\\.Thread\\.State:\\s+(?<state>[A-Z_]+)(?:\\s+\\((?<sub>[^)]+)\\))?/;\nconst frameRe = /^\\s*at\\s+(?<fn>[^\\s(]+)\\((?<src>[^)]+)\\)\\s*$/;\nconst srcLineRe = /^(?<file>[^:]+):(?<line>\\d+)$/;\nconst annotationRe =\n /^\\s*-\\s+(?<kind>locked|waiting on|waiting to lock|parking to wait for)\\b(?<rest>.*)$/;\n\nexport function parseJvmThreadDump(text: string): ParsedThread[] {\n const trimmed = text.trim();\n if (!trimmed) return [];\n\n // Split on blank lines OR on a new `\"...\"` header that follows immediately.\n const blocks = splitIntoThreadBlocks(trimmed);\n const threads: ParsedThread[] = [];\n\n for (const block of blocks) {\n const parsed = parseThreadBlock(block);\n if (parsed) threads.push(parsed);\n }\n return threads;\n}\n\nfunction splitIntoThreadBlocks(text: string): string[] {\n const out: string[] = [];\n let current: string[] = [];\n const lines = text.split(\"\\n\");\n for (const raw of lines) {\n const line = raw.replace(/\\r$/, \"\");\n if (line.startsWith('\"') && current.length > 0) {\n out.push(current.join(\"\\n\"));\n current = [line];\n } else {\n current.push(line);\n }\n }\n if (current.length > 0) out.push(current.join(\"\\n\"));\n return out;\n}\n\nfunction parseThreadBlock(block: string): ParsedThread | null {\n const lines = block.split(\"\\n\");\n const header = lines[0]?.trim() ?? \"\";\n const headerMatch = headerRe.exec(header);\n if (!headerMatch?.groups) return null;\n\n const name = headerMatch.groups.name;\n if (!name) return null;\n const rest = headerMatch.groups.rest ?? \"\";\n const idMatch = /#(\\d+)\\b/.exec(rest);\n const prioMatch = /\\bprio=(\\d+)/.exec(rest);\n const nidMatch = /\\bnid=(0x[0-9a-f]+)/i.exec(rest);\n const daemon = /\\bdaemon\\b/.test(rest);\n const headerStateTrail = extractHeaderStateTrail(rest);\n\n let rawState = headerStateTrail ?? \"\";\n let state = normalizeJvmState(rawState);\n const frames: ParsedThreadFrame[] = [];\n\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n if (line == null) continue;\n if (!line.trim()) continue;\n\n const stateMatch = stateRe.exec(line);\n if (stateMatch?.groups) {\n const primary = stateMatch.groups.state;\n if (!primary) continue;\n const sub = stateMatch.groups.sub;\n rawState = sub ? `${primary} (${sub})` : primary;\n state = normalizeJvmState(primary);\n continue;\n }\n\n const frameMatch = frameRe.exec(line);\n if (frameMatch?.groups) {\n const functionName = frameMatch.groups.fn;\n const src = frameMatch.groups.src;\n if (!functionName || !src) continue;\n const frame: ParsedThreadFrame = {\n functionName,\n displayName: sanitizeJvmFunctionName(functionName),\n kind: \"frame\",\n runtime: isJvmRuntimeFrame(functionName),\n nativeMethod: src === \"Native Method\",\n ...splitClassMethod(functionName),\n };\n const srcMatch = srcLineRe.exec(src);\n if (srcMatch?.groups?.file && srcMatch.groups.line) {\n frame.file = srcMatch.groups.file;\n frame.line = Number(srcMatch.groups.line);\n frame.location = `${frame.file}:${frame.line}`;\n } else if (src === \"Native Method\") {\n frame.location = \"Native Method\";\n } else {\n frame.location = src;\n }\n frames.push(frame);\n continue;\n }\n\n const annoMatch = annotationRe.exec(line);\n if (annoMatch?.groups?.kind) {\n const annotationKind = annoMatch.groups.kind;\n const kind = mapAnnotationKind(annotationKind);\n frames.push({\n functionName: annotationKind,\n displayName: annotationKind,\n kind,\n runtime: false,\n nativeMethod: false,\n annotationText: (annoMatch.groups.rest ?? \"\").trim(),\n });\n continue;\n }\n }\n\n const userFrameCount = frames.filter((f) => f.kind === \"frame\" && !f.runtime).length;\n const topFunction = frames.find((f) => f.kind === \"frame\")?.functionName;\n const searchText = [\n header,\n ...frames.map((f) => `${f.functionName} ${f.location ?? \"\"} ${f.annotationText ?? \"\"}`),\n ]\n .join(\"\\n\")\n .toLowerCase();\n\n return {\n id: idMatch ? Number(idMatch[1]) : deriveSyntheticId(name, rest),\n name,\n state: state || \"unknown\",\n rawState: rawState || \"\",\n daemon,\n frames,\n raw: block,\n userFrameCount,\n searchText,\n ...(nidMatch?.[1] !== undefined ? { nid: nidMatch[1] } : {}),\n ...(prioMatch?.[1] !== undefined ? { priority: Number(prioMatch[1]) } : {}),\n ...(topFunction !== undefined ? { topFunction } : {}),\n };\n}\n\nfunction extractHeaderStateTrail(rest: string): string | undefined {\n const lower = rest.toLowerCase();\n const marker = \"nid=0x\";\n const markerStart = lower.indexOf(marker);\n if (markerStart === -1) return undefined;\n\n let stateStart = markerStart + marker.length;\n const hexStart = stateStart;\n while (isHexDigit(rest[stateStart])) stateStart++;\n if (stateStart === hexStart || !isWhitespace(rest[stateStart])) return undefined;\n while (isWhitespace(rest[stateStart])) stateStart++;\n\n let stateEnd = rest.length;\n while (stateEnd > stateStart && isWhitespace(rest[stateEnd - 1])) stateEnd--;\n if (rest[stateEnd - 1] === \"]\") {\n const addressStart = lower.lastIndexOf(\"[0x\", stateEnd - 1);\n if (\n addressStart > stateStart &&\n isHexSequence(rest, addressStart + 3, stateEnd - 1) &&\n isWhitespace(rest[addressStart - 1])\n ) {\n stateEnd = addressStart;\n while (stateEnd > stateStart && isWhitespace(rest[stateEnd - 1])) stateEnd--;\n }\n }\n\n const state = rest.slice(stateStart, stateEnd);\n return state || undefined;\n}\n\nfunction isHexDigit(value: string | undefined): boolean {\n if (value === undefined) return false;\n const code = value.toLowerCase().charCodeAt(0);\n return (code >= 48 && code <= 57) || (code >= 97 && code <= 102);\n}\n\nfunction isHexSequence(value: string, start: number, end: number): boolean {\n if (start >= end) return false;\n for (let index = start; index < end; index++) {\n if (!isHexDigit(value[index])) return false;\n }\n return true;\n}\n\nfunction isWhitespace(value: string | undefined): boolean {\n return value !== undefined && value.trim() === \"\";\n}\n\nfunction deriveSyntheticId(name: string, rest: string): number {\n const tid = /\\btid=(0x[0-9a-f]+)/i.exec(rest);\n if (tid?.[1]) {\n // stable non-negative int derived from tid hex suffix\n const hex = tid[1].slice(2);\n const n = Number.parseInt(hex.slice(-8), 16);\n if (Number.isFinite(n)) return n;\n }\n // Fallback: hash of name\n let h = 0;\n for (let i = 0; i < name.length; i++) h = (h * 31 + name.charCodeAt(i)) | 0;\n return Math.abs(h);\n}\n\nfunction mapAnnotationKind(kind: string): ParsedThreadFrame[\"kind\"] {\n switch (kind) {\n case \"locked\":\n return \"locked\";\n case \"waiting on\":\n return \"waiting_on\";\n case \"waiting to lock\":\n return \"waiting_to_lock\";\n case \"parking to wait for\":\n return \"parking\";\n default:\n return \"frame\";\n }\n}\n\nexport function countThreadsByState(threads: ParsedThread[]): Map<string, number> {\n const counts = new Map<string, number>();\n for (const t of threads) counts.set(t.state, (counts.get(t.state) ?? 0) + 1);\n return counts;\n}\n\nfunction normalizeJvmState(value: string): string {\n if (!value) return \"\";\n const upper = value.trim().toUpperCase();\n if (upper.startsWith(\"RUNNABLE\")) return \"runnable\";\n if (upper.startsWith(\"TIMED_WAITING\")) return \"timed_waiting\";\n if (upper.startsWith(\"WAITING\")) return \"waiting\";\n if (upper.startsWith(\"BLOCKED\")) return \"blocked\";\n if (upper.startsWith(\"NEW\")) return \"new\";\n if (upper.startsWith(\"TERMINATED\")) return \"terminated\";\n // Header fragments like \"waiting on condition\", \"runnable\", \"sleeping\"\n const lower = value.trim().toLowerCase();\n if (lower.includes(\"runnable\")) return \"runnable\";\n if (lower.includes(\"waiting on condition\") || lower.includes(\"sleeping\")) return \"timed_waiting\";\n if (lower.includes(\"waiting\")) return \"waiting\";\n if (lower.includes(\"blocked\")) return \"blocked\";\n return lower.split(/\\s+/)[0] ?? \"\";\n}\n\nconst runtimePrefixes = [\"java.\", \"javax.\", \"sun.\", \"jdk.\", \"com.sun.\", \"or\" + \"acle.jrockit.\"];\nfunction isJvmRuntimeFrame(functionName: string): boolean {\n return runtimePrefixes.some((p) => functionName.startsWith(p));\n}\n\n// splitClassMethod separates a JVM frame's `fully.qualified.Class.method` into\n// its class and method. The method is the last dot segment; everything before\n// is the (possibly inner) class. Returns no fields when the name has no dot, so\n// frames like a bare `<init>` are left without a class rather than guessed.\nfunction splitClassMethod(functionName: string): { class?: string; method?: string } {\n const lastDot = functionName.lastIndexOf(\".\");\n if (lastDot <= 0) return {};\n return {\n class: functionName.slice(0, lastDot),\n method: functionName.slice(lastDot + 1),\n };\n}\n\nfunction sanitizeJvmFunctionName(functionName: string): string {\n // e.g. \"com.example.App$Inner.method\" → \"App$Inner.method\"\n const parts = functionName.split(\".\");\n if (parts.length < 2) return functionName;\n const method = parts[parts.length - 1];\n const cls = parts[parts.length - 2];\n return `${cls}.${method}`;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"jvm-stacktrace.cjs","sources":["../../../src/data/diagnostics/jvm-stacktrace.ts"],"sourcesContent":["import { isRuntimeFrame, shortFrameName } from \"./frame-heuristics\";\n\nexport interface ParsedThreadFrame {\n functionName: string;\n displayName: string;\n file?: string;\n line?: number;\n location?: string;\n kind: \"frame\" | \"locked\" | \"waiting_on\" | \"waiting_to_lock\" | \"parking\";\n runtime: boolean;\n nativeMethod: boolean;\n annotationText?: string;\n // Optional fully-qualified class name (e.g. \"com.example.admin.pas.Foo\").\n // Lets renderers filter or group by package without re-splitting\n // functionName. Populated by parseJavaStackTrace; left undefined by the\n // thread-dump parser since its frames are raw \"fn(src)\" pairs.\n class?: string;\n method?: string;\n // Optional source-context window populated by clicky.SourceResolver\n // (or its TS equivalent). sourceLines[line - sourceStartLine] is the focal\n // line. Empty/undefined when no resolver was attached.\n sourceLines?: string[];\n sourceLineNumbers?: number[];\n sourceStartLine?: number;\n sourceLanguage?: string;\n}\n\nexport interface ParsedThread {\n id: number;\n nid?: string;\n name: string;\n state: string;\n rawState: string;\n priority?: number;\n daemon?: boolean;\n frames: ParsedThreadFrame[];\n raw: string;\n userFrameCount: number;\n topFunction?: string;\n searchText: string;\n}\n\nconst headerRe = /^\"(?<name>[^\"]*)\"(?<rest>.*)$/;\nconst stateRe = /^\\s*java\\.lang\\.Thread\\.State:\\s+(?<state>[A-Z_]+)(?:\\s+\\((?<sub>[^)]+)\\))?/;\nconst frameRe = /^\\s*at\\s+(?<fn>[^\\s(]+)\\((?<src>[^)]+)\\)\\s*$/;\nconst srcLineRe = /^(?<file>[^:]+):(?<line>\\d+)$/;\nconst annotationRe =\n /^\\s*-\\s+(?<kind>locked|waiting on|waiting to lock|parking to wait for)\\b(?<rest>.*)$/;\n\nexport function parseJvmThreadDump(text: string): ParsedThread[] {\n const trimmed = text.trim();\n if (!trimmed) return [];\n\n // Split on blank lines OR on a new `\"...\"` header that follows immediately.\n const blocks = splitIntoThreadBlocks(trimmed);\n const threads: ParsedThread[] = [];\n\n for (const block of blocks) {\n const parsed = parseThreadBlock(block);\n if (parsed) threads.push(parsed);\n }\n return threads;\n}\n\nfunction splitIntoThreadBlocks(text: string): string[] {\n const out: string[] = [];\n let current: string[] = [];\n const lines = text.split(\"\\n\");\n for (const raw of lines) {\n const line = raw.replace(/\\r$/, \"\");\n if (line.startsWith('\"') && current.length > 0) {\n out.push(current.join(\"\\n\"));\n current = [line];\n } else {\n current.push(line);\n }\n }\n if (current.length > 0) out.push(current.join(\"\\n\"));\n return out;\n}\n\nfunction parseThreadBlock(block: string): ParsedThread | null {\n const lines = block.split(\"\\n\");\n const header = lines[0]?.trim() ?? \"\";\n const headerMatch = headerRe.exec(header);\n if (!headerMatch?.groups) return null;\n\n const name = headerMatch.groups.name;\n if (!name) return null;\n const rest = headerMatch.groups.rest ?? \"\";\n const idMatch = /#(\\d+)\\b/.exec(rest);\n const prioMatch = /\\bprio=(\\d+)/.exec(rest);\n const nidMatch = /\\bnid=(0x[0-9a-f]+)/i.exec(rest);\n const daemon = /\\bdaemon\\b/.test(rest);\n const headerStateTrail = extractHeaderStateTrail(rest);\n\n let rawState = headerStateTrail ?? \"\";\n let state = normalizeJvmState(rawState);\n const frames: ParsedThreadFrame[] = [];\n\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n if (line == null) continue;\n if (!line.trim()) continue;\n\n const stateMatch = stateRe.exec(line);\n if (stateMatch?.groups) {\n const primary = stateMatch.groups.state;\n if (!primary) continue;\n const sub = stateMatch.groups.sub;\n rawState = sub ? `${primary} (${sub})` : primary;\n state = normalizeJvmState(primary);\n continue;\n }\n\n const frameMatch = frameRe.exec(line);\n if (frameMatch?.groups) {\n const functionName = frameMatch.groups.fn;\n const src = frameMatch.groups.src;\n if (!functionName || !src) continue;\n const frame: ParsedThreadFrame = {\n functionName,\n displayName: sanitizeJvmFunctionName(functionName),\n kind: \"frame\",\n runtime: isJvmRuntimeFrame(functionName),\n nativeMethod: src === \"Native Method\",\n ...splitClassMethod(functionName),\n };\n const srcMatch = srcLineRe.exec(src);\n if (srcMatch?.groups?.file && srcMatch.groups.line) {\n frame.file = srcMatch.groups.file;\n frame.line = Number(srcMatch.groups.line);\n frame.location = `${frame.file}:${frame.line}`;\n } else if (src === \"Native Method\") {\n frame.location = \"Native Method\";\n } else {\n frame.location = src;\n }\n frames.push(frame);\n continue;\n }\n\n const annoMatch = annotationRe.exec(line);\n if (annoMatch?.groups?.kind) {\n const annotationKind = annoMatch.groups.kind;\n const kind = mapAnnotationKind(annotationKind);\n frames.push({\n functionName: annotationKind,\n displayName: annotationKind,\n kind,\n runtime: false,\n nativeMethod: false,\n annotationText: (annoMatch.groups.rest ?? \"\").trim(),\n });\n continue;\n }\n }\n\n const userFrameCount = frames.filter((f) => f.kind === \"frame\" && !f.runtime).length;\n const topFunction = frames.find((f) => f.kind === \"frame\")?.functionName;\n const searchText = [\n header,\n ...frames.map((f) => `${f.functionName} ${f.location ?? \"\"} ${f.annotationText ?? \"\"}`),\n ]\n .join(\"\\n\")\n .toLowerCase();\n\n return {\n id: idMatch ? Number(idMatch[1]) : deriveSyntheticId(name, rest),\n name,\n state: state || \"unknown\",\n rawState: rawState || \"\",\n daemon,\n frames,\n raw: block,\n userFrameCount,\n searchText,\n ...(nidMatch?.[1] !== undefined ? { nid: nidMatch[1] } : {}),\n ...(prioMatch?.[1] !== undefined ? { priority: Number(prioMatch[1]) } : {}),\n ...(topFunction !== undefined ? { topFunction } : {}),\n };\n}\n\nfunction extractHeaderStateTrail(rest: string): string | undefined {\n const lower = rest.toLowerCase();\n const marker = \"nid=0x\";\n const markerStart = lower.indexOf(marker);\n if (markerStart === -1) return undefined;\n\n let stateStart = markerStart + marker.length;\n const hexStart = stateStart;\n while (isHexDigit(rest[stateStart])) stateStart++;\n if (stateStart === hexStart || !isWhitespace(rest[stateStart])) return undefined;\n while (isWhitespace(rest[stateStart])) stateStart++;\n\n let stateEnd = rest.length;\n while (stateEnd > stateStart && isWhitespace(rest[stateEnd - 1])) stateEnd--;\n if (rest[stateEnd - 1] === \"]\") {\n const addressStart = lower.lastIndexOf(\"[0x\", stateEnd - 1);\n if (\n addressStart > stateStart &&\n isHexSequence(rest, addressStart + 3, stateEnd - 1) &&\n isWhitespace(rest[addressStart - 1])\n ) {\n stateEnd = addressStart;\n while (stateEnd > stateStart && isWhitespace(rest[stateEnd - 1])) stateEnd--;\n }\n }\n\n const state = rest.slice(stateStart, stateEnd);\n return state || undefined;\n}\n\nfunction isHexDigit(value: string | undefined): boolean {\n if (value === undefined) return false;\n const code = value.toLowerCase().charCodeAt(0);\n return (code >= 48 && code <= 57) || (code >= 97 && code <= 102);\n}\n\nfunction isHexSequence(value: string, start: number, end: number): boolean {\n if (start >= end) return false;\n for (let index = start; index < end; index++) {\n if (!isHexDigit(value[index])) return false;\n }\n return true;\n}\n\nfunction isWhitespace(value: string | undefined): boolean {\n return value !== undefined && value.trim() === \"\";\n}\n\nfunction deriveSyntheticId(name: string, rest: string): number {\n const tid = /\\btid=(0x[0-9a-f]+)/i.exec(rest);\n if (tid?.[1]) {\n // stable non-negative int derived from tid hex suffix\n const hex = tid[1].slice(2);\n const n = Number.parseInt(hex.slice(-8), 16);\n if (Number.isFinite(n)) return n;\n }\n // Fallback: hash of name\n let h = 0;\n for (let i = 0; i < name.length; i++) h = (h * 31 + name.charCodeAt(i)) | 0;\n return Math.abs(h);\n}\n\nfunction mapAnnotationKind(kind: string): ParsedThreadFrame[\"kind\"] {\n switch (kind) {\n case \"locked\":\n return \"locked\";\n case \"waiting on\":\n return \"waiting_on\";\n case \"waiting to lock\":\n return \"waiting_to_lock\";\n case \"parking to wait for\":\n return \"parking\";\n default:\n return \"frame\";\n }\n}\n\nexport function countThreadsByState(threads: ParsedThread[]): Map<string, number> {\n const counts = new Map<string, number>();\n for (const t of threads) counts.set(t.state, (counts.get(t.state) ?? 0) + 1);\n return counts;\n}\n\nfunction normalizeJvmState(value: string): string {\n if (!value) return \"\";\n const upper = value.trim().toUpperCase();\n if (upper.startsWith(\"RUNNABLE\")) return \"runnable\";\n if (upper.startsWith(\"TIMED_WAITING\")) return \"timed_waiting\";\n if (upper.startsWith(\"WAITING\")) return \"waiting\";\n if (upper.startsWith(\"BLOCKED\")) return \"blocked\";\n if (upper.startsWith(\"NEW\")) return \"new\";\n if (upper.startsWith(\"TERMINATED\")) return \"terminated\";\n // Header fragments like \"waiting on condition\", \"runnable\", \"sleeping\"\n const lower = value.trim().toLowerCase();\n if (lower.includes(\"runnable\")) return \"runnable\";\n if (lower.includes(\"waiting on condition\") || lower.includes(\"sleeping\")) return \"timed_waiting\";\n if (lower.includes(\"waiting\")) return \"waiting\";\n if (lower.includes(\"blocked\")) return \"blocked\";\n return lower.split(/\\s+/)[0] ?? \"\";\n}\n\nfunction isJvmRuntimeFrame(functionName: string): boolean {\n return isRuntimeFrame(functionName);\n}\n\n// splitClassMethod separates a JVM frame's `fully.qualified.Class.method` into\n// its class and method. The method is the last dot segment; everything before\n// is the (possibly inner) class. Returns no fields when the name has no dot, so\n// frames like a bare `<init>` are left without a class rather than guessed.\nfunction splitClassMethod(functionName: string): { class?: string; method?: string } {\n const lastDot = functionName.lastIndexOf(\".\");\n if (lastDot <= 0) return {};\n return {\n class: functionName.slice(0, lastDot),\n method: functionName.slice(lastDot + 1),\n };\n}\n\nfunction sanitizeJvmFunctionName(functionName: string): string {\n // e.g. \"com.example.App$Inner.method\" → \"App$Inner.method\"\n const lastDot = functionName.lastIndexOf(\".\");\n if (lastDot <= 0) return functionName;\n return shortFrameName(functionName.slice(0, lastDot), functionName.slice(lastDot + 1));\n}\n"],"names":["isRuntimeFrame","shortFrameName"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"jvm-stacktrace.d.ts","sourceRoot":"","sources":["../../../src/data/diagnostics/jvm-stacktrace.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,YAAY,GAAG,iBAAiB,GAAG,SAAS,CAAC;IACxE,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IAKxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAIhB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AASD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CAa/D;AAsMD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAIhF"}
1
+ {"version":3,"file":"jvm-stacktrace.d.ts","sourceRoot":"","sources":["../../../src/data/diagnostics/jvm-stacktrace.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,YAAY,GAAG,iBAAiB,GAAG,SAAS,CAAC;IACxE,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IAKxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAIhB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AASD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CAa/D;AAsMD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAIhF"}
@@ -1,3 +1,4 @@
1
+ import { isRuntimeFrame, shortFrameName } from "./frame-heuristics.js";
1
2
  const headerRe = /^"(?<name>[^"]*)"(?<rest>.*)$/;
2
3
  const stateRe = /^\s*java\.lang\.Thread\.State:\s+(?<state>[A-Z_]+)(?:\s+\((?<sub>[^)]+)\))?/;
3
4
  const frameRe = /^\s*at\s+(?<fn>[^\s(]+)\((?<src>[^)]+)\)\s*$/;
@@ -205,9 +206,8 @@ function normalizeJvmState(value) {
205
206
  if (lower.includes("blocked")) return "blocked";
206
207
  return lower.split(/\s+/)[0] ?? "";
207
208
  }
208
- const runtimePrefixes = ["java.", "javax.", "sun.", "jdk.", "com.sun.", "oracle.jrockit."];
209
209
  function isJvmRuntimeFrame(functionName) {
210
- return runtimePrefixes.some((p) => functionName.startsWith(p));
210
+ return isRuntimeFrame(functionName);
211
211
  }
212
212
  function splitClassMethod(functionName) {
213
213
  const lastDot = functionName.lastIndexOf(".");
@@ -218,11 +218,9 @@ function splitClassMethod(functionName) {
218
218
  };
219
219
  }
220
220
  function sanitizeJvmFunctionName(functionName) {
221
- const parts = functionName.split(".");
222
- if (parts.length < 2) return functionName;
223
- const method = parts[parts.length - 1];
224
- const cls = parts[parts.length - 2];
225
- return `${cls}.${method}`;
221
+ const lastDot = functionName.lastIndexOf(".");
222
+ if (lastDot <= 0) return functionName;
223
+ return shortFrameName(functionName.slice(0, lastDot), functionName.slice(lastDot + 1));
226
224
  }
227
225
  export {
228
226
  countThreadsByState,
@@ -1 +1 @@
1
- {"version":3,"file":"jvm-stacktrace.js","sources":["../../../src/data/diagnostics/jvm-stacktrace.ts"],"sourcesContent":["export interface ParsedThreadFrame {\n functionName: string;\n displayName: string;\n file?: string;\n line?: number;\n location?: string;\n kind: \"frame\" | \"locked\" | \"waiting_on\" | \"waiting_to_lock\" | \"parking\";\n runtime: boolean;\n nativeMethod: boolean;\n annotationText?: string;\n // Optional fully-qualified class name (e.g. \"com.example.admin.pas.Foo\").\n // Lets renderers filter or group by package without re-splitting\n // functionName. Populated by parseJavaStackTrace; left undefined by the\n // thread-dump parser since its frames are raw \"fn(src)\" pairs.\n class?: string;\n method?: string;\n // Optional source-context window populated by clicky.SourceResolver\n // (or its TS equivalent). sourceLines[line - sourceStartLine] is the focal\n // line. Empty/undefined when no resolver was attached.\n sourceLines?: string[];\n sourceLineNumbers?: number[];\n sourceStartLine?: number;\n sourceLanguage?: string;\n}\n\nexport interface ParsedThread {\n id: number;\n nid?: string;\n name: string;\n state: string;\n rawState: string;\n priority?: number;\n daemon?: boolean;\n frames: ParsedThreadFrame[];\n raw: string;\n userFrameCount: number;\n topFunction?: string;\n searchText: string;\n}\n\nconst headerRe = /^\"(?<name>[^\"]*)\"(?<rest>.*)$/;\nconst stateRe = /^\\s*java\\.lang\\.Thread\\.State:\\s+(?<state>[A-Z_]+)(?:\\s+\\((?<sub>[^)]+)\\))?/;\nconst frameRe = /^\\s*at\\s+(?<fn>[^\\s(]+)\\((?<src>[^)]+)\\)\\s*$/;\nconst srcLineRe = /^(?<file>[^:]+):(?<line>\\d+)$/;\nconst annotationRe =\n /^\\s*-\\s+(?<kind>locked|waiting on|waiting to lock|parking to wait for)\\b(?<rest>.*)$/;\n\nexport function parseJvmThreadDump(text: string): ParsedThread[] {\n const trimmed = text.trim();\n if (!trimmed) return [];\n\n // Split on blank lines OR on a new `\"...\"` header that follows immediately.\n const blocks = splitIntoThreadBlocks(trimmed);\n const threads: ParsedThread[] = [];\n\n for (const block of blocks) {\n const parsed = parseThreadBlock(block);\n if (parsed) threads.push(parsed);\n }\n return threads;\n}\n\nfunction splitIntoThreadBlocks(text: string): string[] {\n const out: string[] = [];\n let current: string[] = [];\n const lines = text.split(\"\\n\");\n for (const raw of lines) {\n const line = raw.replace(/\\r$/, \"\");\n if (line.startsWith('\"') && current.length > 0) {\n out.push(current.join(\"\\n\"));\n current = [line];\n } else {\n current.push(line);\n }\n }\n if (current.length > 0) out.push(current.join(\"\\n\"));\n return out;\n}\n\nfunction parseThreadBlock(block: string): ParsedThread | null {\n const lines = block.split(\"\\n\");\n const header = lines[0]?.trim() ?? \"\";\n const headerMatch = headerRe.exec(header);\n if (!headerMatch?.groups) return null;\n\n const name = headerMatch.groups.name;\n if (!name) return null;\n const rest = headerMatch.groups.rest ?? \"\";\n const idMatch = /#(\\d+)\\b/.exec(rest);\n const prioMatch = /\\bprio=(\\d+)/.exec(rest);\n const nidMatch = /\\bnid=(0x[0-9a-f]+)/i.exec(rest);\n const daemon = /\\bdaemon\\b/.test(rest);\n const headerStateTrail = extractHeaderStateTrail(rest);\n\n let rawState = headerStateTrail ?? \"\";\n let state = normalizeJvmState(rawState);\n const frames: ParsedThreadFrame[] = [];\n\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n if (line == null) continue;\n if (!line.trim()) continue;\n\n const stateMatch = stateRe.exec(line);\n if (stateMatch?.groups) {\n const primary = stateMatch.groups.state;\n if (!primary) continue;\n const sub = stateMatch.groups.sub;\n rawState = sub ? `${primary} (${sub})` : primary;\n state = normalizeJvmState(primary);\n continue;\n }\n\n const frameMatch = frameRe.exec(line);\n if (frameMatch?.groups) {\n const functionName = frameMatch.groups.fn;\n const src = frameMatch.groups.src;\n if (!functionName || !src) continue;\n const frame: ParsedThreadFrame = {\n functionName,\n displayName: sanitizeJvmFunctionName(functionName),\n kind: \"frame\",\n runtime: isJvmRuntimeFrame(functionName),\n nativeMethod: src === \"Native Method\",\n ...splitClassMethod(functionName),\n };\n const srcMatch = srcLineRe.exec(src);\n if (srcMatch?.groups?.file && srcMatch.groups.line) {\n frame.file = srcMatch.groups.file;\n frame.line = Number(srcMatch.groups.line);\n frame.location = `${frame.file}:${frame.line}`;\n } else if (src === \"Native Method\") {\n frame.location = \"Native Method\";\n } else {\n frame.location = src;\n }\n frames.push(frame);\n continue;\n }\n\n const annoMatch = annotationRe.exec(line);\n if (annoMatch?.groups?.kind) {\n const annotationKind = annoMatch.groups.kind;\n const kind = mapAnnotationKind(annotationKind);\n frames.push({\n functionName: annotationKind,\n displayName: annotationKind,\n kind,\n runtime: false,\n nativeMethod: false,\n annotationText: (annoMatch.groups.rest ?? \"\").trim(),\n });\n continue;\n }\n }\n\n const userFrameCount = frames.filter((f) => f.kind === \"frame\" && !f.runtime).length;\n const topFunction = frames.find((f) => f.kind === \"frame\")?.functionName;\n const searchText = [\n header,\n ...frames.map((f) => `${f.functionName} ${f.location ?? \"\"} ${f.annotationText ?? \"\"}`),\n ]\n .join(\"\\n\")\n .toLowerCase();\n\n return {\n id: idMatch ? Number(idMatch[1]) : deriveSyntheticId(name, rest),\n name,\n state: state || \"unknown\",\n rawState: rawState || \"\",\n daemon,\n frames,\n raw: block,\n userFrameCount,\n searchText,\n ...(nidMatch?.[1] !== undefined ? { nid: nidMatch[1] } : {}),\n ...(prioMatch?.[1] !== undefined ? { priority: Number(prioMatch[1]) } : {}),\n ...(topFunction !== undefined ? { topFunction } : {}),\n };\n}\n\nfunction extractHeaderStateTrail(rest: string): string | undefined {\n const lower = rest.toLowerCase();\n const marker = \"nid=0x\";\n const markerStart = lower.indexOf(marker);\n if (markerStart === -1) return undefined;\n\n let stateStart = markerStart + marker.length;\n const hexStart = stateStart;\n while (isHexDigit(rest[stateStart])) stateStart++;\n if (stateStart === hexStart || !isWhitespace(rest[stateStart])) return undefined;\n while (isWhitespace(rest[stateStart])) stateStart++;\n\n let stateEnd = rest.length;\n while (stateEnd > stateStart && isWhitespace(rest[stateEnd - 1])) stateEnd--;\n if (rest[stateEnd - 1] === \"]\") {\n const addressStart = lower.lastIndexOf(\"[0x\", stateEnd - 1);\n if (\n addressStart > stateStart &&\n isHexSequence(rest, addressStart + 3, stateEnd - 1) &&\n isWhitespace(rest[addressStart - 1])\n ) {\n stateEnd = addressStart;\n while (stateEnd > stateStart && isWhitespace(rest[stateEnd - 1])) stateEnd--;\n }\n }\n\n const state = rest.slice(stateStart, stateEnd);\n return state || undefined;\n}\n\nfunction isHexDigit(value: string | undefined): boolean {\n if (value === undefined) return false;\n const code = value.toLowerCase().charCodeAt(0);\n return (code >= 48 && code <= 57) || (code >= 97 && code <= 102);\n}\n\nfunction isHexSequence(value: string, start: number, end: number): boolean {\n if (start >= end) return false;\n for (let index = start; index < end; index++) {\n if (!isHexDigit(value[index])) return false;\n }\n return true;\n}\n\nfunction isWhitespace(value: string | undefined): boolean {\n return value !== undefined && value.trim() === \"\";\n}\n\nfunction deriveSyntheticId(name: string, rest: string): number {\n const tid = /\\btid=(0x[0-9a-f]+)/i.exec(rest);\n if (tid?.[1]) {\n // stable non-negative int derived from tid hex suffix\n const hex = tid[1].slice(2);\n const n = Number.parseInt(hex.slice(-8), 16);\n if (Number.isFinite(n)) return n;\n }\n // Fallback: hash of name\n let h = 0;\n for (let i = 0; i < name.length; i++) h = (h * 31 + name.charCodeAt(i)) | 0;\n return Math.abs(h);\n}\n\nfunction mapAnnotationKind(kind: string): ParsedThreadFrame[\"kind\"] {\n switch (kind) {\n case \"locked\":\n return \"locked\";\n case \"waiting on\":\n return \"waiting_on\";\n case \"waiting to lock\":\n return \"waiting_to_lock\";\n case \"parking to wait for\":\n return \"parking\";\n default:\n return \"frame\";\n }\n}\n\nexport function countThreadsByState(threads: ParsedThread[]): Map<string, number> {\n const counts = new Map<string, number>();\n for (const t of threads) counts.set(t.state, (counts.get(t.state) ?? 0) + 1);\n return counts;\n}\n\nfunction normalizeJvmState(value: string): string {\n if (!value) return \"\";\n const upper = value.trim().toUpperCase();\n if (upper.startsWith(\"RUNNABLE\")) return \"runnable\";\n if (upper.startsWith(\"TIMED_WAITING\")) return \"timed_waiting\";\n if (upper.startsWith(\"WAITING\")) return \"waiting\";\n if (upper.startsWith(\"BLOCKED\")) return \"blocked\";\n if (upper.startsWith(\"NEW\")) return \"new\";\n if (upper.startsWith(\"TERMINATED\")) return \"terminated\";\n // Header fragments like \"waiting on condition\", \"runnable\", \"sleeping\"\n const lower = value.trim().toLowerCase();\n if (lower.includes(\"runnable\")) return \"runnable\";\n if (lower.includes(\"waiting on condition\") || lower.includes(\"sleeping\")) return \"timed_waiting\";\n if (lower.includes(\"waiting\")) return \"waiting\";\n if (lower.includes(\"blocked\")) return \"blocked\";\n return lower.split(/\\s+/)[0] ?? \"\";\n}\n\nconst runtimePrefixes = [\"java.\", \"javax.\", \"sun.\", \"jdk.\", \"com.sun.\", \"or\" + \"acle.jrockit.\"];\nfunction isJvmRuntimeFrame(functionName: string): boolean {\n return runtimePrefixes.some((p) => functionName.startsWith(p));\n}\n\n// splitClassMethod separates a JVM frame's `fully.qualified.Class.method` into\n// its class and method. The method is the last dot segment; everything before\n// is the (possibly inner) class. Returns no fields when the name has no dot, so\n// frames like a bare `<init>` are left without a class rather than guessed.\nfunction splitClassMethod(functionName: string): { class?: string; method?: string } {\n const lastDot = functionName.lastIndexOf(\".\");\n if (lastDot <= 0) return {};\n return {\n class: functionName.slice(0, lastDot),\n method: functionName.slice(lastDot + 1),\n };\n}\n\nfunction sanitizeJvmFunctionName(functionName: string): string {\n // e.g. \"com.example.App$Inner.method\" → \"App$Inner.method\"\n const parts = functionName.split(\".\");\n if (parts.length < 2) return functionName;\n const method = parts[parts.length - 1];\n const cls = parts[parts.length - 2];\n return `${cls}.${method}`;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"jvm-stacktrace.js","sources":["../../../src/data/diagnostics/jvm-stacktrace.ts"],"sourcesContent":["import { isRuntimeFrame, shortFrameName } from \"./frame-heuristics\";\n\nexport interface ParsedThreadFrame {\n functionName: string;\n displayName: string;\n file?: string;\n line?: number;\n location?: string;\n kind: \"frame\" | \"locked\" | \"waiting_on\" | \"waiting_to_lock\" | \"parking\";\n runtime: boolean;\n nativeMethod: boolean;\n annotationText?: string;\n // Optional fully-qualified class name (e.g. \"com.example.admin.pas.Foo\").\n // Lets renderers filter or group by package without re-splitting\n // functionName. Populated by parseJavaStackTrace; left undefined by the\n // thread-dump parser since its frames are raw \"fn(src)\" pairs.\n class?: string;\n method?: string;\n // Optional source-context window populated by clicky.SourceResolver\n // (or its TS equivalent). sourceLines[line - sourceStartLine] is the focal\n // line. Empty/undefined when no resolver was attached.\n sourceLines?: string[];\n sourceLineNumbers?: number[];\n sourceStartLine?: number;\n sourceLanguage?: string;\n}\n\nexport interface ParsedThread {\n id: number;\n nid?: string;\n name: string;\n state: string;\n rawState: string;\n priority?: number;\n daemon?: boolean;\n frames: ParsedThreadFrame[];\n raw: string;\n userFrameCount: number;\n topFunction?: string;\n searchText: string;\n}\n\nconst headerRe = /^\"(?<name>[^\"]*)\"(?<rest>.*)$/;\nconst stateRe = /^\\s*java\\.lang\\.Thread\\.State:\\s+(?<state>[A-Z_]+)(?:\\s+\\((?<sub>[^)]+)\\))?/;\nconst frameRe = /^\\s*at\\s+(?<fn>[^\\s(]+)\\((?<src>[^)]+)\\)\\s*$/;\nconst srcLineRe = /^(?<file>[^:]+):(?<line>\\d+)$/;\nconst annotationRe =\n /^\\s*-\\s+(?<kind>locked|waiting on|waiting to lock|parking to wait for)\\b(?<rest>.*)$/;\n\nexport function parseJvmThreadDump(text: string): ParsedThread[] {\n const trimmed = text.trim();\n if (!trimmed) return [];\n\n // Split on blank lines OR on a new `\"...\"` header that follows immediately.\n const blocks = splitIntoThreadBlocks(trimmed);\n const threads: ParsedThread[] = [];\n\n for (const block of blocks) {\n const parsed = parseThreadBlock(block);\n if (parsed) threads.push(parsed);\n }\n return threads;\n}\n\nfunction splitIntoThreadBlocks(text: string): string[] {\n const out: string[] = [];\n let current: string[] = [];\n const lines = text.split(\"\\n\");\n for (const raw of lines) {\n const line = raw.replace(/\\r$/, \"\");\n if (line.startsWith('\"') && current.length > 0) {\n out.push(current.join(\"\\n\"));\n current = [line];\n } else {\n current.push(line);\n }\n }\n if (current.length > 0) out.push(current.join(\"\\n\"));\n return out;\n}\n\nfunction parseThreadBlock(block: string): ParsedThread | null {\n const lines = block.split(\"\\n\");\n const header = lines[0]?.trim() ?? \"\";\n const headerMatch = headerRe.exec(header);\n if (!headerMatch?.groups) return null;\n\n const name = headerMatch.groups.name;\n if (!name) return null;\n const rest = headerMatch.groups.rest ?? \"\";\n const idMatch = /#(\\d+)\\b/.exec(rest);\n const prioMatch = /\\bprio=(\\d+)/.exec(rest);\n const nidMatch = /\\bnid=(0x[0-9a-f]+)/i.exec(rest);\n const daemon = /\\bdaemon\\b/.test(rest);\n const headerStateTrail = extractHeaderStateTrail(rest);\n\n let rawState = headerStateTrail ?? \"\";\n let state = normalizeJvmState(rawState);\n const frames: ParsedThreadFrame[] = [];\n\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n if (line == null) continue;\n if (!line.trim()) continue;\n\n const stateMatch = stateRe.exec(line);\n if (stateMatch?.groups) {\n const primary = stateMatch.groups.state;\n if (!primary) continue;\n const sub = stateMatch.groups.sub;\n rawState = sub ? `${primary} (${sub})` : primary;\n state = normalizeJvmState(primary);\n continue;\n }\n\n const frameMatch = frameRe.exec(line);\n if (frameMatch?.groups) {\n const functionName = frameMatch.groups.fn;\n const src = frameMatch.groups.src;\n if (!functionName || !src) continue;\n const frame: ParsedThreadFrame = {\n functionName,\n displayName: sanitizeJvmFunctionName(functionName),\n kind: \"frame\",\n runtime: isJvmRuntimeFrame(functionName),\n nativeMethod: src === \"Native Method\",\n ...splitClassMethod(functionName),\n };\n const srcMatch = srcLineRe.exec(src);\n if (srcMatch?.groups?.file && srcMatch.groups.line) {\n frame.file = srcMatch.groups.file;\n frame.line = Number(srcMatch.groups.line);\n frame.location = `${frame.file}:${frame.line}`;\n } else if (src === \"Native Method\") {\n frame.location = \"Native Method\";\n } else {\n frame.location = src;\n }\n frames.push(frame);\n continue;\n }\n\n const annoMatch = annotationRe.exec(line);\n if (annoMatch?.groups?.kind) {\n const annotationKind = annoMatch.groups.kind;\n const kind = mapAnnotationKind(annotationKind);\n frames.push({\n functionName: annotationKind,\n displayName: annotationKind,\n kind,\n runtime: false,\n nativeMethod: false,\n annotationText: (annoMatch.groups.rest ?? \"\").trim(),\n });\n continue;\n }\n }\n\n const userFrameCount = frames.filter((f) => f.kind === \"frame\" && !f.runtime).length;\n const topFunction = frames.find((f) => f.kind === \"frame\")?.functionName;\n const searchText = [\n header,\n ...frames.map((f) => `${f.functionName} ${f.location ?? \"\"} ${f.annotationText ?? \"\"}`),\n ]\n .join(\"\\n\")\n .toLowerCase();\n\n return {\n id: idMatch ? Number(idMatch[1]) : deriveSyntheticId(name, rest),\n name,\n state: state || \"unknown\",\n rawState: rawState || \"\",\n daemon,\n frames,\n raw: block,\n userFrameCount,\n searchText,\n ...(nidMatch?.[1] !== undefined ? { nid: nidMatch[1] } : {}),\n ...(prioMatch?.[1] !== undefined ? { priority: Number(prioMatch[1]) } : {}),\n ...(topFunction !== undefined ? { topFunction } : {}),\n };\n}\n\nfunction extractHeaderStateTrail(rest: string): string | undefined {\n const lower = rest.toLowerCase();\n const marker = \"nid=0x\";\n const markerStart = lower.indexOf(marker);\n if (markerStart === -1) return undefined;\n\n let stateStart = markerStart + marker.length;\n const hexStart = stateStart;\n while (isHexDigit(rest[stateStart])) stateStart++;\n if (stateStart === hexStart || !isWhitespace(rest[stateStart])) return undefined;\n while (isWhitespace(rest[stateStart])) stateStart++;\n\n let stateEnd = rest.length;\n while (stateEnd > stateStart && isWhitespace(rest[stateEnd - 1])) stateEnd--;\n if (rest[stateEnd - 1] === \"]\") {\n const addressStart = lower.lastIndexOf(\"[0x\", stateEnd - 1);\n if (\n addressStart > stateStart &&\n isHexSequence(rest, addressStart + 3, stateEnd - 1) &&\n isWhitespace(rest[addressStart - 1])\n ) {\n stateEnd = addressStart;\n while (stateEnd > stateStart && isWhitespace(rest[stateEnd - 1])) stateEnd--;\n }\n }\n\n const state = rest.slice(stateStart, stateEnd);\n return state || undefined;\n}\n\nfunction isHexDigit(value: string | undefined): boolean {\n if (value === undefined) return false;\n const code = value.toLowerCase().charCodeAt(0);\n return (code >= 48 && code <= 57) || (code >= 97 && code <= 102);\n}\n\nfunction isHexSequence(value: string, start: number, end: number): boolean {\n if (start >= end) return false;\n for (let index = start; index < end; index++) {\n if (!isHexDigit(value[index])) return false;\n }\n return true;\n}\n\nfunction isWhitespace(value: string | undefined): boolean {\n return value !== undefined && value.trim() === \"\";\n}\n\nfunction deriveSyntheticId(name: string, rest: string): number {\n const tid = /\\btid=(0x[0-9a-f]+)/i.exec(rest);\n if (tid?.[1]) {\n // stable non-negative int derived from tid hex suffix\n const hex = tid[1].slice(2);\n const n = Number.parseInt(hex.slice(-8), 16);\n if (Number.isFinite(n)) return n;\n }\n // Fallback: hash of name\n let h = 0;\n for (let i = 0; i < name.length; i++) h = (h * 31 + name.charCodeAt(i)) | 0;\n return Math.abs(h);\n}\n\nfunction mapAnnotationKind(kind: string): ParsedThreadFrame[\"kind\"] {\n switch (kind) {\n case \"locked\":\n return \"locked\";\n case \"waiting on\":\n return \"waiting_on\";\n case \"waiting to lock\":\n return \"waiting_to_lock\";\n case \"parking to wait for\":\n return \"parking\";\n default:\n return \"frame\";\n }\n}\n\nexport function countThreadsByState(threads: ParsedThread[]): Map<string, number> {\n const counts = new Map<string, number>();\n for (const t of threads) counts.set(t.state, (counts.get(t.state) ?? 0) + 1);\n return counts;\n}\n\nfunction normalizeJvmState(value: string): string {\n if (!value) return \"\";\n const upper = value.trim().toUpperCase();\n if (upper.startsWith(\"RUNNABLE\")) return \"runnable\";\n if (upper.startsWith(\"TIMED_WAITING\")) return \"timed_waiting\";\n if (upper.startsWith(\"WAITING\")) return \"waiting\";\n if (upper.startsWith(\"BLOCKED\")) return \"blocked\";\n if (upper.startsWith(\"NEW\")) return \"new\";\n if (upper.startsWith(\"TERMINATED\")) return \"terminated\";\n // Header fragments like \"waiting on condition\", \"runnable\", \"sleeping\"\n const lower = value.trim().toLowerCase();\n if (lower.includes(\"runnable\")) return \"runnable\";\n if (lower.includes(\"waiting on condition\") || lower.includes(\"sleeping\")) return \"timed_waiting\";\n if (lower.includes(\"waiting\")) return \"waiting\";\n if (lower.includes(\"blocked\")) return \"blocked\";\n return lower.split(/\\s+/)[0] ?? \"\";\n}\n\nfunction isJvmRuntimeFrame(functionName: string): boolean {\n return isRuntimeFrame(functionName);\n}\n\n// splitClassMethod separates a JVM frame's `fully.qualified.Class.method` into\n// its class and method. The method is the last dot segment; everything before\n// is the (possibly inner) class. Returns no fields when the name has no dot, so\n// frames like a bare `<init>` are left without a class rather than guessed.\nfunction splitClassMethod(functionName: string): { class?: string; method?: string } {\n const lastDot = functionName.lastIndexOf(\".\");\n if (lastDot <= 0) return {};\n return {\n class: functionName.slice(0, lastDot),\n method: functionName.slice(lastDot + 1),\n };\n}\n\nfunction sanitizeJvmFunctionName(functionName: string): string {\n // e.g. \"com.example.App$Inner.method\" → \"App$Inner.method\"\n const lastDot = functionName.lastIndexOf(\".\");\n if (lastDot <= 0) return functionName;\n return shortFrameName(functionName.slice(0, lastDot), functionName.slice(lastDot + 1));\n}\n"],"names":[],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const frameHeuristics = require("./frame-heuristics.cjs");
3
4
  const frameRe = /^\s*at\s+([\w$.]+)\.([\w$<>]+)\(([^)]+)\)/;
4
5
  const continuationRe = /^\.\.\.\s+\d+\s+more$/;
5
- const runtimePrefixes = ["java.", "javax.", "sun.", "jdk.", "com.sun.", "oracle.jrockit."];
6
6
  function parseJavaStackTrace(input) {
7
7
  const out = {
8
8
  causedBy: [],
@@ -77,12 +77,12 @@ function buildFrame(cls, method, locRaw) {
77
77
  }
78
78
  }
79
79
  const functionName = `${cls}.${method}`;
80
- const location = file ? line ? `${file}:${line}` : file : nativeMethod ? "Native Method" : void 0;
80
+ const location = frameHeuristics.frameLocation(file, line) ?? (nativeMethod ? "Native Method" : void 0);
81
81
  const frame = {
82
82
  functionName,
83
- displayName: shortDisplay(cls, method),
83
+ displayName: frameHeuristics.shortFrameName(cls, method),
84
84
  kind: "frame",
85
- runtime: runtimePrefixes.some((p) => cls.startsWith(p)),
85
+ runtime: frameHeuristics.isRuntimeFrame(cls),
86
86
  nativeMethod,
87
87
  class: cls,
88
88
  method
@@ -92,10 +92,5 @@ function buildFrame(cls, method, locRaw) {
92
92
  if (location !== void 0) frame.location = location;
93
93
  return frame;
94
94
  }
95
- function shortDisplay(cls, method) {
96
- const parts = cls.split(".");
97
- const last = parts[parts.length - 1] ?? cls;
98
- return `${last}.${method}`;
99
- }
100
95
  exports.parseJavaStackTrace = parseJavaStackTrace;
101
96
  //# sourceMappingURL=stacktrace-parse.cjs.map