Repository navigation
Implement CSS Custom Highlight API for Code OSS ranges #740
Description
Active implementation checkpoint — 20 September 2026
Exact upstream heads are WebScene 3cc78ac28101e23f07ded947b44869277da6632d and AppScene acf42662309ea601720ed07c440cf183d7c73fe3; unchanged Code OSS is 645f29cc3176500b4b5762ba887cf2a7f0ffdf2c. Local vscode-demo is 06b5fa4328bae547e40462cbd049b6322f8e8d8e, clean, 294 commits ahead, and intentionally unpushed with Actions disabled.
Focused merge stacks
- Worker/resource stack — merged: WebScene Load dynamically inserted CSS imports asynchronously #702, Complete WorkerOptions and worker load policy #703, Enforce Worker policy across redirect hops #705 and Expose fetch request headers to resource hosts #707; AppScene Expose CSS retained-effect computed values #282; local vscode-demo Add native WebGPU runtime support #10. Dynamic CSS imports, Worker options/credentials/CORS, per-hop redirect validation, and request-header ABI v5 are on main.
- Interactive validation stack — merged: WebScene Present bounded interactive reportValidity feedback #709, Fix validation message text measurement #711, Dismiss stale validation feedback after mutations #712, Bound validation message wrapping and formatting #718, Add bounded validation message formatter ABI #721, Add bounded validation message timeout #723, Bound form ownership invalidation #724, Reflect form labels in semantic validity #725, Implement bounded custom element states #726, Implement live form control collections #727, Implement bounded form state restoration #728 and Wire Flutter validation localization #729; AppScene Wake native runtime for queued WebSocket events #284; local vscode-demo Broaden WebScene compatibility coverage and release gates #11. This includes focused invalid reporting, text-measurement repair, stale-feedback dismissal, bounded wrapping, localization ABI, optional timeout scheduling, and mutation-local form/fieldset ownership invalidation.
- Selector/pseudo stack — merged through scoped selection: WebScene Complete selector matching, specificity, and dependency invalidation coverage #237/Match live hyperlink selector state #730, Implement bounded local-link selector state #735, Implement bounded target-within selector state #736 and Implement functional local-link path depth #737 merged live location selectors; Paint Code OSS placeholder pseudo styles #738 merged paint-only Code OSS
::placeholder; Implement static Code OSS details content #739 merged the bounded static subset for the ten unchanged Code OSS::details-contentrules. Native GitHub stack #745 merged atomically as Implement live Range boundaries for Code OSS highlights #742 (live Range boundaries), Add Highlight and CSS.highlights registry for Code OSS #744 (bounded Highlight/CSS.highlights registry), and Paint CSS Custom Highlight ranges for Code OSS (#746) #747 (functional::highlight(name)theme cascade plus retained range paint), closing Implement CSS Custom Highlight API for Code OSS ranges #740/Implement live Range boundaries for Code OSS highlights #741/Add Highlight and CSS.highlights registry for Code OSS #743/Paint CSS Custom Highlight ranges for Code OSS #746 at main7a2d0f8d. PR Paint scoped selection ranges for Code OSS #751 then merged global/scoped::selectioncascade, theme colors, forward/backward range normalization, and retained background/foreground commands at main2c83b45f, closing Paint scoped ::selection ranges for Code OSS and xterm #750. Focused native/compiler run35469464706and precompiled contracts35469464714passed. Details animation/compositing, control-part/shadow-selector inventory, and remaining CSS work stay recorded in Complete selector matching, specificity, and dependency invalidation coverage #237/[Epic] CSS features, compatibility, validation, and performance #235. - Typed transition stack — merged: WebScene PR Implement typed registered custom-property animations #752 merged typed
<angle>/<percentage>@propertysupport. PR Implement Code OSS starting-style entry transitions #753 then merged Implement @starting-style entry transitions used by Code OSS #749 at main3cc78ac2, adding document-level@starting-style, precedence-correct starting cascades, first-render/display re-entry, opacity/2D transform/background-color admission,transition-behavior: allow-discrete, computed-versus-used display behavior,CSSStartingStyleRule, detached-state release, reinsertion, teardown, and a zero-allocation guard across 256 unrelated nodes. Focused precompiled JavaScript35473084845, Linux native SDK35473084825, and native Linux document contracts35473084848passed. - Consolidations — open and deliberately unmerged: WebScene Add Code OSS browser and native desktop compatibility #76 is refreshed to
ed2eb2c57ec6b1a8bda4bd75747379a7c19c86cf; AppScene Stream native application video directly from file and network URLs #65 is at2d2407f5e38c4cdd3d851394a5636cc0a8ce9064; vscode-demo Typescript #1 tracks the local unpushed integration branch.
One-agent mode is enforced. No subagent is active. Reusable runtime behavior continues to land in WebScene or AppScene; unchanged Code OSS remains pinned. The change-related #752 and #753 runs passed. Broad PR CI/NuGet plus consolidation, post-merge main and previous-main runs were canceled to release runners; no WebScene job is intentionally retained between focused PRs. Full package, performance, visual, physical-platform and VM qualification remains deferred under the fast implementation directive; focused parser/native correctness and allocation checks are complete locally.
Next: finish the remaining planned CSS and product features, then physical Linux pixels, synchronization/device-loss/resize/soak/performance, visual comparison, VM/computer-use, and unchanged Code OSS Release qualification. Rich clipboard MIME, MULTIPLE/SAVE_TARGETS, recorded desktop-service/cross-platform work, workspace/Explorer, file/save, terminal, Markdown preview, accessibility, lifecycle, package-size, and no-browser promotion gates remain tracked and incomplete.
Parent: #237
Epic: #235
Related webview acceptance: #264
Problem
Unchanged Code OSS uses the CSS Custom Highlight API for chat find and Markdown inner-diff rendering:
src/vs/workbench/contrib/chat/browser/widget/chatFind/chatFindWidget.cssdefines::highlight(chat-find-current-match)and::highlight(chat-find-other-match)with foreground/background colors.chatFindHighlights.tsconstructs textRangeobjects, updatesHighlightsets, assignspriority, and publishes them throughCSS.highlights.- the Markdown extension defines
::highlight(diff-inner-added/deleted), constructs boundary-marker ranges, and replaces registry entries.
WebScene recognizes neither functional ::highlight(<custom-ident>) nor the Highlight/CSS.highlights APIs. Its current document.createRange() object is a contextual-fragment helper with a no-op selectNodeContents; it does not retain boundary points. Code OSS therefore falls back or loses the intended native range paint.
Proposed implementation
- Add retained live
Rangeboundary state for the Code OSS paths:new Range()anddocument.createRange(),setStart,setEnd,setStartAfter,setEndBefore,selectNodeContents, boundary getters, collapsed state, and detach-safe validation. - Add the
Highlightsetlike subset used by unchanged Code OSS: constructor ranges,add,delete,clear,has,size, iteration, andpriority. - Add a document-local
CSS.highlightsmaplike registry withset,get,has,delete,clear, size/iteration semantics, name validation, replacement, and bounded ownership. - Parse
::highlight(<custom-ident>)without confusing nested selector syntax. Retain the exact Code OSS paint subset:colorandbackground-color, including custom-property resolution and cascade/source order. - Convert live text-range intersections into retained paint spans without creating DOM/visual-tree nodes. Respect registry priority and registration order for overlap.
- Revalidate only ranges whose boundary subtree or text changed. Remove detached/invalid ranges and release persistent handles during navigation, nested-context teardown, low-memory cleanup, and engine destruction.
- Request a frame only when registry/range/style changes alter visible highlight paint. Static highlights must cause zero idle frames and no selector/tree rescans per frame.
Acceptance and gates
- Unchanged Code OSS chat find current/other matches paint with authored foreground/background and update when owners replace or clear ranges.
- Markdown added/deleted inner ranges paint across marker boundaries and disappear on registry deletion.
- Range UTF-16 offsets, cross-text-node boundaries, collapsed ranges, reversed invalid inputs, detached nodes, replacement, overlap priority, custom properties, and stylesheet mutation have focused contracts.
- Text mutation and reparent/detach cannot retain stale node pointers or paint outside the live range.
- Work counters stay proportional to changed highlights and intersected text fragments, independent of unrelated DOM/rules/highlight names.
- Static highlighted scenes request zero idle frames; repeated set/delete and navigation return native nodes, V8 handles, heap/RSS, scene commands, and frame demand to baseline.
- Browser/native contracts and unchanged Code OSS visual regions are compared in the later consolidated qualification pass.
- No Code OSS source changes and no browser/WebView/Electron/CEF dependency.
Explicit remainder
Complete DOM Range editing/extraction APIs, arbitrary highlight pseudo properties, spelling/grammar/target-text pseudos, and general Selection API completion remain separate work.
Activity
wieslawsoltes commentedon Sep 19, 2026
Implemented and merged atomically through native GitHub stack #745: #742 (Range), #744 (Highlight/CSS.highlights registry), and #747 (::highlight cascade plus retained paint). Top-stack gates passed in native document/compiler contracts run 35468506202, including the independent native-only SDK build, and precompiled JavaScript contracts run 35468506209. Broad duplicate/package CI was canceled under the agreed top-of-stack focused validation policy. Merge head: 7a2d0f8.