markdown: fix scroll sync regressions introduced in #287050#307763
Conversation
Two regressions from the merge of microsoft#287050: 1. preview.ts: The merge retained `this.#isScrolling = false` inside the early-return guard of `scrollTo()`, which was intentionally removed in the original PR. This resets the timer-based flag on the very first forward-sync call, allowing subsequent editor scroll events to re-trigger forward sync while reverse sync is in progress, causing the editor to jump back up. 2. index.ts: The PR converted `onUpdateView` from a decrement-counter to a timer-based approach but left initialization and resize handlers still using `scrollDisabledCount += 1` without a corresponding timer reset. The old scroll handler decremented the counter naturally; the new handler only returns early. As a result, after page load `scrollDisabledCount` stays at 1 indefinitely, blocking all preview-to-editor sync until the user scrolls the editor once. Fixes: - Remove the erroneous `this.#isScrolling = false` from scrollTo() - Apply the same timer-reset pattern (200ms) to initialization and resize handlers so scrollDisabledCount is always auto-cleared Fixes microsoft#307762
|
At this point |
There was a problem hiding this comment.
Pull request overview
Fixes markdown preview/editor scroll sync regressions introduced by #287050, restoring correct forward/reverse scroll synchronization behavior in the Markdown preview.
Changes:
- Prevents editor “jumping” during preview-driven scroll sync by not resetting the in-progress scrolling guard in
scrollTo(). - Ensures preview → editor sync works immediately after load by applying a timer-based reset to all remaining
scrollDisabledCountincrement sites (restore/fragment/line/resize paths).
Show a summary per file
| File | Description |
|---|---|
| extensions/markdown-language-features/src/preview/preview.ts | Removes an incorrect #isScrolling reset inside scrollTo()’s early-return guard to prevent re-entrant sync. |
| extensions/markdown-language-features/preview-src/index.ts | Applies the timer-reset pattern consistently to initialization/fragment/line/resize handlers so preview → editor sync isn’t permanently blocked. |
Copilot's findings
Comments suppressed due to low confidence (3)
extensions/markdown-language-features/preview-src/index.ts:120
- This repeats the same scroll-disable/timer-reset block used in other places in this file. To keep behavior consistent and avoid missing one site in the future, consider refactoring this into a shared helper and reusing it here.
scrollDisabledCount = 1;
if (scrollDisabledTimer) { clearTimeout(scrollDisabledTimer); }
scrollDisabledTimer = window.setTimeout(() => { scrollDisabledCount = 0; }, 200);
extensions/markdown-language-features/preview-src/index.ts:127
- Same duplicated scroll-disable/timer-reset logic as the other initialization paths. Consider using a shared helper (and potentially a constant for the delay) instead of repeating the block in multiple branches.
scrollDisabledCount = 1;
if (scrollDisabledTimer) { clearTimeout(scrollDisabledTimer); }
scrollDisabledTimer = window.setTimeout(() => { scrollDisabledCount = 0; }, 200);
extensions/markdown-language-features/preview-src/index.ts:163
- The scroll-disable/timer-reset logic is duplicated across multiple handlers (restore/fragment/line/resize). A helper would reduce duplication and make it less likely for future edits to accidentally diverge between sites.
scrollDisabledCount = 1;
if (scrollDisabledTimer) { clearTimeout(scrollDisabledTimer); }
scrollDisabledTimer = window.setTimeout(() => { scrollDisabledCount = 0; }, 200);
- Files reviewed: 2/2 changed files
- Comments generated: 1
| scrollDisabledCount = 1; | ||
| if (scrollDisabledTimer) { clearTimeout(scrollDisabledTimer); } | ||
| scrollDisabledTimer = window.setTimeout(() => { scrollDisabledCount = 0; }, 200); |
There was a problem hiding this comment.
The scroll-disable/timer-reset sequence is duplicated here and again at the fragment/line handling and resize handler. Consider extracting a small helper (e.g. disableScrollFor(ms)) and/or a named constant for the 200ms delay to avoid future inconsistencies and reduce copy/paste.
This issue also appears in the following locations of the same file:
- line 118
- line 125
- line 161
Fixes #307762
Bug 1: Editor jumps when scrolling the preview (
preview.ts)The merge retained
this.#isScrolling = falseinside the early-return guard ofscrollTo(), which the original PR intentionally removed. This resets the timer on the first call, letting subsequent editor scroll events re-trigger forward sync while reverse sync is still in progress.if (this.#isScrolling) { - this.#isScrolling = false; return; }Bug 2: Preview → editor sync requires editor to be scrolled first (
index.ts)The PR switched
onUpdateViewto a timer-based reset but left initialization and resize handlers still usingscrollDisabledCount += 1with no timer. Since the scroll handler no longer decrements,scrollDisabledCountstays at1after page load and blocks all preview-to-editor sync.Fix: apply the same timer-reset pattern (200ms) to all four remaining increment sites.