From d3c4cc513802540e510afc5afce369c699df5d33 Mon Sep 17 00:00:00 2001 From: Luke Cotter <4013877+lukecotter@users.noreply.github.com> Date: Wed, 22 Jul 2026 23:39:17 +0100 Subject: [PATCH 1/2] fix(timeline): guard minimap density against fractional display width (#863) Windows fractional display scaling (125/150/175%) makes getBoundingClientRect().width non-integer; passing it to MinimapDensityQuery as a bucket count threw "Invalid array length" and aborted timeline init before interaction handlers attached, so zoom/pan/keys all appeared dead. Floor the count at the single query() entry point. Bump 1.20.1. --- CHANGELOG.md | 7 ++++ lana/package.json | 2 +- .../__tests__/minimap-density.test.ts | 35 +++++++++++++++++++ .../optimised/minimap/MinimapDensityQuery.ts | 8 +++++ 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b7fc94c..11620311 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.20.1] 2026-07-22 + +### Fixed + +- 🪟 **Timeline on Windows**: fixed the Flame Chart failing to load — with zoom, pan and keyboard navigation all appearing unresponsive — under fractional display scaling (125% / 150% / 175%). ([#863]) + ## [1.20.0] 2026-06-18 ### Added @@ -659,3 +665,4 @@ Skipped due to adopting odd numbering for pre releases and even number for relea [#242]: https://github.com/certinia/debug-log-analyzer/issues/242 [#235]: https://github.com/certinia/debug-log-analyzer/issues/235 [#264]: https://github.com/certinia/debug-log-analyzer/issues/264 +[#863]: https://github.com/certinia/debug-log-analyzer/issues/863 diff --git a/lana/package.json b/lana/package.json index 88dc4dd0..b6421753 100644 --- a/lana/package.json +++ b/lana/package.json @@ -1,7 +1,7 @@ { "name": "lana", "displayName": "Apex Log Analyzer", - "version": "1.20.0", + "version": "1.20.1", "description": "Salesforce Apex Debug Log Analyzer: Blazing-fast VS Code extension for Salesforce. Visualize and debug Apex logs with interactive flame charts, dynamic call trees, and detailed SOQL/DML breakdowns. Identify performance bottlenecks, gain deep transaction insights and optimize slow Apex.", "keywords": [ "analysis", diff --git a/log-viewer/src/features/timeline/__tests__/minimap-density.test.ts b/log-viewer/src/features/timeline/__tests__/minimap-density.test.ts index 53dbdb3f..d033ed4a 100644 --- a/log-viewer/src/features/timeline/__tests__/minimap-density.test.ts +++ b/log-viewer/src/features/timeline/__tests__/minimap-density.test.ts @@ -196,4 +196,39 @@ describe('MinimapDensityQuery', () => { expect(result.buckets).toHaveLength(0); }); }); + + describe('fractional bucket count (Windows fractional DPI scaling)', () => { + // Regression: getBoundingClientRect().width is non-integer under Windows + // 125%/150% display scaling; a fractional/NaN count previously threw + // "Invalid array length" and aborted timeline init. + const rects = [createRect('Method', 0, 1000, 0)]; + + it('floors a fractional bucket count instead of throwing (segment tree path)', () => { + const rectsByCategory = buildRectsByCategory(rects); + const segmentTree = new TemporalSegmentTree(rectsByCategory); + const query = new MinimapDensityQuery(rectsByCategory, 1000, 0, segmentTree); + + const fractional = query.query(10.6); + const floored = query.query(10); + + expect(fractional.buckets).toHaveLength(10); + expect(fractional.buckets).toEqual(floored.buckets); + }); + + it('floors a fractional bucket count instead of throwing (fallback path)', () => { + const rectsByCategory = buildRectsByCategory(rects); + const query = new MinimapDensityQuery(rectsByCategory, 1000, 0); + + expect(() => query.query(1536.6667)).not.toThrow(); + expect(query.query(1536.6667).buckets).toHaveLength(1536); + }); + + it('treats a non-finite bucket count as empty instead of throwing', () => { + const rectsByCategory = buildRectsByCategory(rects); + const query = new MinimapDensityQuery(rectsByCategory, 1000, 0); + + expect(() => query.query(Number.NaN)).not.toThrow(); + expect(query.query(Number.NaN).buckets).toHaveLength(0); + }); + }); }); diff --git a/log-viewer/src/features/timeline/optimised/minimap/MinimapDensityQuery.ts b/log-viewer/src/features/timeline/optimised/minimap/MinimapDensityQuery.ts index 26ecf89f..a2b3ea9b 100644 --- a/log-viewer/src/features/timeline/optimised/minimap/MinimapDensityQuery.ts +++ b/log-viewer/src/features/timeline/optimised/minimap/MinimapDensityQuery.ts @@ -164,6 +164,14 @@ export class MinimapDensityQuery { * @returns MinimapDensityData for rendering */ public query(bucketCount: number): MinimapDensityData { + // bucketCount is the display width from getBoundingClientRect(), which is + // fractional under non-integer OS display scaling (Windows 125%/150% DPI). + // A fractional/NaN count crashes the Array/typed-array constructors below + // with "Invalid array length" (the `<= 0` guards do not catch it), which + // aborts timeline init and leaves interaction handlers unwired. Normalise + // here, the single entry point feeding both compute paths and the cache. + bucketCount = Number.isFinite(bucketCount) ? Math.floor(bucketCount) : 0; + // Fast path: exact match in cache const cached = this.densityCache.get(bucketCount); if (cached) { From ceb36158ca383068120a6f07046e8fddd1139594 Mon Sep 17 00:00:00 2001 From: Luke Cotter <4013877+lukecotter@users.noreply.github.com> Date: Thu, 23 Jul 2026 09:08:18 +0100 Subject: [PATCH 2/2] docs: update changelog 1.20.1 date --- CHANGELOG.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11620311..bcfde01c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [1.20.1] 2026-07-22 +## [1.20.1] 2026-07-23 ### Fixed -- 🪟 **Timeline on Windows**: fixed the Flame Chart failing to load — with zoom, pan and keyboard navigation all appearing unresponsive — under fractional display scaling (125% / 150% / 175%). ([#863]) +- 🪟 **Timeline on Windows**: fixed the Flame Chart failing to load due to fractional display scaling (125% / 150% / 175%) - zoom, pan and keyboard navigation all appeared unresponsive ([#863]). ## [1.20.0] 2026-06-18 @@ -491,6 +491,10 @@ Skipped due to adopting odd numbering for pre releases and even number for relea - Add explorer menu item. - Provide more information when selecting log to download. + + +[#863]: https://github.com/certinia/debug-log-analyzer/issues/863 + [#605]: https://github.com/certinia/debug-log-analyzer/issues/605 @@ -665,4 +669,3 @@ Skipped due to adopting odd numbering for pre releases and even number for relea [#242]: https://github.com/certinia/debug-log-analyzer/issues/242 [#235]: https://github.com/certinia/debug-log-analyzer/issues/235 [#264]: https://github.com/certinia/debug-log-analyzer/issues/264 -[#863]: https://github.com/certinia/debug-log-analyzer/issues/863