diff --git a/Lib/profiling/sampling/_heatmap_assets/heatmap.css b/Lib/profiling/sampling/_heatmap_assets/heatmap.css index 65a13d7245d5c4..9999cd6760fd49 100644 --- a/Lib/profiling/sampling/_heatmap_assets/heatmap.css +++ b/Lib/profiling/sampling/_heatmap_assets/heatmap.css @@ -1141,6 +1141,10 @@ .line-samples-cumulative { padding: 0 4px; } + + .bytecode-panel { + margin: 8px 10px 8px 160px; + } } .bytecode-toggle { @@ -1172,13 +1176,77 @@ } .bytecode-panel { - margin-left: 90px; - padding: 8px 15px; - background: var(--bg-secondary); - border-left: 3px solid var(--accent); + background: var(--bg-primary); + border: 1px solid var(--border); + border-radius: 8px; + box-shadow: var(--shadow-md); font-family: var(--font-mono); font-size: 12px; - margin-bottom: 4px; + color: var(--text-primary); + line-height: 1.5; + word-wrap: break-word; + overflow-wrap: break-word; + padding: 0; + margin: 8px 10px 8px 250px; + position: relative; + z-index: 1; + overflow-y: auto; + max-height: 500px; + flex: 1; + transition: padding 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +.bytecode-panel.expanded { + padding: 14px; +} + +.bytecode-wrapper { + position: relative; + display: flex; + overflow: visible; + max-height: 0; + opacity: 0; + transition: max-height 0.4s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease-in-out; +} + +.bytecode-wrapper.expanded { + max-height: 600px; + opacity: 1; + transition: max-height 0.5s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.4s ease-in-out; +} + +/* Column backdrop matching table header columns (line/self/total) */ +.bytecode-columns { + display: none; + position: absolute; + left: 0; + overflow: hidden; + pointer-events: none; + z-index: 0; +} + +.bytecode-wrapper.expanded .bytecode-columns { + display: flex; + top: 0; + bottom: 0; +} + +.bytecode-panel::-webkit-scrollbar { + width: 8px; +} + +.bytecode-panel::-webkit-scrollbar-track { + background: var(--bg-secondary); + border-radius: 4px; +} + +.bytecode-panel::-webkit-scrollbar-thumb { + background: var(--border); + border-radius: 4px; +} + +.bytecode-panel::-webkit-scrollbar-thumb:hover { + background: var(--text-muted); } /* Specialization summary bar */ diff --git a/Lib/profiling/sampling/_heatmap_assets/heatmap.js b/Lib/profiling/sampling/_heatmap_assets/heatmap.js index 8ac4ef43e53b37..d6a91ef290309b 100644 --- a/Lib/profiling/sampling/_heatmap_assets/heatmap.js +++ b/Lib/profiling/sampling/_heatmap_assets/heatmap.js @@ -542,20 +542,23 @@ function toggleBytecode(button) { const lineId = lineDiv.id; const lineNum = lineId.replace('line-', ''); const panel = document.getElementById(`bytecode-${lineNum}`); + const wrapper = document.getElementById(`bytecode-wrapper-${lineNum}`); - if (!panel) return; + if (!panel || !wrapper) return; - const isExpanded = panel.style.display !== 'none'; + const isExpanded = panel.classList.contains('expanded'); if (isExpanded) { - panel.style.display = 'none'; + panel.classList.remove('expanded'); + wrapper.classList.remove('expanded'); button.classList.remove('expanded'); button.innerHTML = '▶'; // Right arrow } else { if (!panel.dataset.populated) { populateBytecodePanel(panel, button); } - panel.style.display = 'block'; + panel.classList.add('expanded'); + wrapper.classList.add('expanded'); button.classList.add('expanded'); button.innerHTML = '▼'; // Down arrow } diff --git a/Lib/profiling/sampling/heatmap_collector.py b/Lib/profiling/sampling/heatmap_collector.py index 5b4c89283be08c..e6701901aa385c 100644 --- a/Lib/profiling/sampling/heatmap_collector.py +++ b/Lib/profiling/sampling/heatmap_collector.py @@ -978,7 +978,17 @@ def _build_line_html(self, line_num: int, line_content: str, f'data-spec-pct="{spec_pct}" ' f'onclick="toggleBytecode(this)" title="Show bytecode">▶' ) - bytecode_panel_html = f' \n' + # Wrapper contains columns + content panel + bytecode_panel_html = ( + f'
\n' + f'
' + f'
' + f'
' + f'
' + f'
\n' + f'
\n' + f'
\n' + ) elif self.opcodes_enabled: # Add invisible spacer to maintain consistent indentation when opcodes are enabled bytecode_btn_html = '
'