Skip to content

Implement CSS Custom Highlight API for Code OSS ranges #740

Description

@wieslawsoltes

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

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.css defines ::highlight(chat-find-current-match) and ::highlight(chat-find-other-match) with foreground/background colors.
  • chatFindHighlights.ts constructs text Range objects, updates Highlight sets, assigns priority, and publishes them through CSS.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 Range boundary state for the Code OSS paths: new Range() and document.createRange(), setStart, setEnd, setStartAfter, setEndBefore, selectNodeContents, boundary getters, collapsed state, and detach-safe validation.
  • Add the Highlight setlike subset used by unchanged Code OSS: constructor ranges, add, delete, clear, has, size, iteration, and priority.
  • Add a document-local CSS.highlights maplike registry with set, 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: color and background-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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestsize/XLvscode-oss/plannedPlanned for the AppScene/WebScene VS Code OSS integration

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions