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

  1. wieslawsoltes commented on Sep 19, 2026

    @wieslawsoltes
    CollaboratorAuthor

    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.

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