[Bug]: Manifest visual editor loses tab/scroll state when the XML is edited in the text editor
Maintainer thường phản hồi trong vòng 11 ngày
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 52/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Ít trao đổi
- Công nghệ
- typescript
- Lĩnh vực
- frontend
Hướng nghiên cứu
Bắt đầu với src/manifest-editor/manifest-editor-provider.ts, webview-script.ts, webview-script-applications.ts, webview-content.ts và webview-styles.ts. Theo dõi các cập nhật tài liệu bên ngoài qua phần xử lý lỗi phân tích cú pháp và các trình render danh sách, sau đó xác định cách bảo toàn trạng thái webview hiện có và các offset cuộn. Hoàn thành khi các chỉnh sửa bên ngoài, bao gồm cả XML tạm thời không hợp lệ, vẫn giữ nguyên các tab, các trường đã mở rộng, tiêu điểm và vị trí cuộn mà không tạo ra các nút tab không nhất quán.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Describe the bug
With an AppxManifest.xml open in both the visual manifest editor and the XML text editor, editing and saving the XML causes the visual editor to lose its UI state — the selected top-level tab, the selected per-application sub-tab (Info / Extensions / Visual Assets), any optional fields the user had expanded, and the scroll position.
Confusingly, it only happens for some edits. Changing an attribute value (e.g. Properties/DisplayName, Identity/Version) preserves state. Adding or removing a <Capability> element resets the editor back to the Identity tab / Info sub-tab.
There are two distinct root causes.
Root cause 1 — the webview document is torn down and rebuilt on transiently-invalid XML
vscode.workspace.onDidChangeTextDocument fires on every keystroke, not just on save (src/manifest-editor/manifest-editor-provider.ts:169-182).
If the document fails to parse at any intermediate moment, tryParseOrShowError replaces the whole webview document with the parse-error page (manifest-editor-provider.ts:74-86). Once the XML parses again, showEditorView() assigns a brand-new webviewPanel.webview.html (manifest-editor-provider.ts:89-93).
That is a full script-context teardown, so every piece of state held in webview JS memory is destroyed:
| State | Where it lives | Survives valid→valid edit | Survives valid→invalid→valid edit |
|---|---|---|---|
| Top-level tab | DOM classes | ✅ | ❌ resets to Identity |
| App sub-tab (Info / Extensions / Visual Assets) | activeAppSubTabs — src/manifest-editor/webview-script.ts:24 |
✅ | ❌ resets to Info |
| User-opened optional fields | userOpenedOptionalFields — webview-script.ts:26 |
✅ | ❌ collapse again |
| Scroll position | DOM | ❌ (see root cause 2) | ❌ |
This explains the asymmetry. Verified against @xmldom/xmldom with the same parseManifestXml error handling the extension uses (src/manifest-schema/xml-parser.ts:33):
adding a <Capability> element editing an attribute value
----------------------------- -------------------------
INVALID "<" valid ""
INVALID "<C" valid "1"
INVALID "<Cap" valid "1."
INVALID "<Capability" valid "1.0"
INVALID "<Capability "
INVALID "<Capability Name="
INVALID "<Capability Name=\"x\""
valid "<Capability Name=\"x\" />"
Typing an element passes through many invalid states, each one flipping the webview to the error page and back. Editing a value in place never breaks the XML, so nothing is torn down.
Note that the state is also lost on a genuine VS Code reload, because the webview never persists anything via vscode.setState() (no setState/getState calls anywhere in src/manifest-editor/).
Root cause 2 — scroll position resets on every external edit
.tab-content is the scroll container (overflow-y: auto, src/manifest-editor/webview-styles.ts:76), and renderApplications starts with container.innerHTML = '' (src/manifest-editor/webview-script-applications.ts:71-73). Clearing the list collapses the scroll height, the browser clamps scrollTop to 0, and the subsequent re-render leaves it there. The same pattern applies to the dependencies and resources renderers.
Additionally, external edits call updateWebview(true), and populateForm sets focused = null when forceAll is set (webview-script.ts:283), so focus restore is skipped entirely for these updates.
Two smaller issues found while investigating
- The parse-error page listens for a
retryParsemessage (src/manifest-editor/webview-content.ts:60), but nothing in the extension ever posts it — dead code. The provider callsshowEditorView()directly instead. - When a tab is hidden based on package type, only the
.tab-contenthasactiveremoved; the corresponding.tab-btnkeeps itsactiveclass (webview-script.ts:393-395,:403-405,:413-415vs. the fallback at:417-422). Two tab buttons can end up looking selected at the same time.
To Reproduce
- Open an
AppxManifest.xmlin the visual manifest editor. - Go to the Applications tab and select the Visual Assets sub-tab.
- Open the same file in the XML text editor (
View XML/Open With… > Text Editor). - Type a new
<Capability Name="internetClient" />line inside<Capabilities>(or delete an existing one character by character), then save. Ctrl+Tabback to the visual editor.
Observed: the editor is back on the Identity tab; the Applications sub-tab has reverted to Info; expanded optional fields are collapsed; scroll is at the top.
For contrast, repeat with an edit that keeps the XML valid at every keystroke — e.g. changing Identity/@Version from 1.0.0.0 to 1.0.0.1. The tab and sub-tab selection are preserved (though scroll still resets).
Expected behavior
Switching back to the visual editor after an external XML edit should leave the user exactly where they were: same top-level tab, same per-application sub-tab, same expanded optional fields, same scroll position. Transiently-invalid XML while the user is mid-keystroke in the text editor should not reset the visual editor's UI state.
Suggested fix
- Stop reassigning
webview.htmlfor parse failures — render the parse error as an overlay inside the existing document (and/or debounce it) so transient invalid states never tear down the script context. - Persist UI state (
activeAppSubTabs, active top-level tab,userOpenedOptionalFields, scroll offsets) viavscode.setState()/getState()so it also survives a genuine webview reload. - Save and restore
scrollToparound the list re-renders inrenderApplications/renderResources/ the dependency renderers. - While in there: remove the dead
retryParsehandler and keep.tab-btn.activein sync with.tab-content.activewhen tabs are hidden by package type.
Screenshots
N/A
OS Version and details
Windows 11
- Ngôn ngữ chính
- TypeScript
- Star
- 15
- Fork
- 4
- Merge trung bình
- 10 ngày 10 giờ
- Pull request đã merge (30 ngày)
- 9
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của microsoft/WinAppVSCE
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
microsoft/WinAppVSCE#320 ·
Maintainer thường phản hồi trong vòng 11 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
microsoft/WinAppVSCE#262 ·
Maintainer thường phản hồi trong vòng 11 ngày
-
[Feature]: Update WinUI templates to include launch.json + VSCE RecommendationCó thể đã có người làm @chiaramooney đã nhận 18 ngày trước. Đang mởenhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
microsoft/WinAppVSCE#219 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 11 ngày
-
documentation
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
microsoft/WinAppVSCE#160 ·
Maintainer thường phản hồi trong vòng 11 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
microsoft/WinAppVSCE#159 ·
Maintainer thường phản hồi trong vòng 11 ngày
Tất cả issue của microsoft/WinAppVSCE
Issue tương tự
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 85/100
formbricks/formbricks#9918 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Chat: Resize question overlayĐang mởenhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
thecodacus/pithagoras#364 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 72/100
openclimatefix/quartz-frontend#823 ·
Maintainer thường phản hồi trong vòng 4 ngày
-
area:agent-manager community needs-triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
Maintainer thường phản hồi trong vòng 1 ngày
-
`contacts.create` posts to `/audiences/undefined/contacts` when `audienceId` is undefinedCó thể đã có người làm @RaphaelFakhri đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
resend/resend-node#1176 ·
Maintainer thường phản hồi trong vòng 1 ngày