Skip to content

Match live form-control pseudo-class state and bounded invalidation #257

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 epic: #235. Owning workstreams: selector/invalidation #237, cascade/value resolution #238, and dynamic state/frame scheduling #242.

Proven gap

The character-data audit on draft #245 produced a product-neutral textarea candidate that fails before its mutation assertions: :invalid reads the authored value attribute instead of the live control value, and :placeholder-shown is not implemented. That draft deliberately added no competing fix. Existing #237/#238 acceptance names state mutations generally but has no focused form-state source-of-truth and invalidation matrix.

This issue does not own #245's structural child-list routes/checkpoints. Start implementation only after #245 is rebased or its relevant test is relocated without conflict.

Ordered work

  1. Inventory form-state pseudos used by current contracts and reachable desktop/webview inputs: :valid/:invalid, :required/:optional, :placeholder-shown, :read-only/:read-write, range states, checked/indeterminate, disabled/enabled, and supported user-valid/user-invalid behavior.
  2. Define the live IDL/content-attribute source for input, textarea, select, option, and form state.
  3. Add dependency metadata and one bounded invalidation checkpoint for value, selection, placeholder, required, pattern, range, checked, disabled, reset, and form-owner changes.
  4. Qualify search, Settings, quick-input, issue-reporter, and extension/webview form surfaces that reach the supported slice.

Acceptance and performance gates

  • Chromium/native WPT-derived match and computed-style matrices agree before and after programmatic value writes, native input, attribute mutation, reset, reparenting, and detach/reattach.
  • Selector APIs and stylesheet matching use the same state while preserving the specified distinction between live properties and content attributes.
  • Initial and mutation scene/pixel checks prove focus, placeholder, validation, and disabled styling without stale retained nodes.
  • A 4,096-control matrix records state probes, matched rules, recascade roots/nodes, layout/scene/publication counts, time, allocations, and peak RSS. Unrelated controls/rules do not force full-document work.
  • No duplicate structural invalidation implementation is introduced alongside Optimize structural CSS invalidation and DOM mutation checkpoints #245.

Proposed PR stack

  1. live form-state model + matcher contracts;
  2. dependency invalidation + cascade/scene mutation;
  3. remaining pseudo-class slices and WPT promotion;
  4. bounded performance and unchanged-product acceptance.

Current implementation checkpoint — 20 September 2026

No form-state source worktree remains. The full listed implementation sequence is merged: live control state and validity, submission/FormData/files, form-associated custom elements, ElementInternals validity, interactive reportValidity() feedback, ownership invalidation, labels/ARIA validity reflection, CustomStateSet, live form.elements, and bounded history/autofill restoration through #708–#720 and #713–#717/#721–#729.

This issue remains open only for direct WPT/runtime/product/performance promotion: unchanged Settings/search/quick-input/webview forms, exact pixels, 4,096-control mutation bounds, lifecycle/memory, and cross-platform package evidence. No duplicate source implementation is scheduled. Exact heads are WebScene ef1fa16e100883857804f7b7811ceffbe1a29867, AppScene 762bc24c2fb450385d4e6f963ddf3638b3c258f8, unchanged Code OSS 645f29cc3176500b4b5762ba887cf2a7f0ffdf2c, and local vscode-demo 8e174f84 (clean, 318 commits ahead, intentionally unpushed); current evidence remains zero under the no-validation direction.

Activity

  1. wieslawsoltes commented on Sep 17, 2026

    @wieslawsoltes
    CollaboratorAuthor

    Wave 1 scheduling boundary: begin this issue only after capability-matrix PR #271 lands and draft structural PR #245 is reconciled/settled. Consume #271's exact CSS evidence format and preserve #245's ownership of child-list routes, mutation checkpoints, scaling counters, and its current WPT profile edits.

    The first #257 stack remains: (1) live input/textarea/select state source plus matcher contracts, (2) state dependency metadata and bounded invalidation/cascade/scene mutation, (3) remaining pseudo-class/WPT slices, and (4) 4,096-control performance plus unchanged-product acceptance. No #245-owned source file should be edited until its merge boundary is known.

  2. wieslawsoltes commented on Sep 18, 2026

    @wieslawsoltes
    CollaboratorAuthor

    Taking the first bounded #257 slice from exact WebScene main bea90e8edb14dcb5a4c8e0257117934c3d462ea0.

    Live overlap audit: the only open PR is docs-only #76. Prerequisites #245/#271 and the #338/#339 Spotify resize work are merged; this slice will not extend those resize paths or own #238 value-resolution work.

    Owned boundary for this slice:

    • make :valid, :invalid, and :placeholder-shown consume the existing live input/textarea value state;
    • compile the corresponding required/value/placeholder dependencies;
    • use one bounded dynamic-state invalidation path for programmatic and native value changes, preserving Optimize structural CSS invalidation and DOM mutation checkpoints #245's structural child-list machinery;
    • promote the existing six-case css-textarea-dynamic-state.html contract only with direct Chromium parity;
    • add focused selector/computed-style, mutation/lifecycle, scene, 4,096-control cascade/layout timing, heap, and RSS evidence.

    Excluded: remaining form pseudos, full constraint validation/pattern/range algorithms, reset/form-owner work, general cascade/value serialization (#238), animation/media scheduling (#242), and further #338/#339 resize optimization. I will re-audit live PR paths before commit and PR.

  3. wieslawsoltes commented on Sep 18, 2026

    @wieslawsoltes
    CollaboratorAuthor

    First bounded live form-control state slice merged via PR #342 as 348ea440501c4059da6f95d1fbd6f6159a5df47b (source 0d6d95a8e3007b833cbfa289f413bc70218d2f2d).

    Landed behavior:

    • :valid / :invalid and :placeholder-shown consume live input/textarea value state;
    • programmatic value changes, native edits, content-attribute/default-value synchronization, form reset, detach/reattach, and required/placeholder mutations route through bounded dependency invalidation;
    • empty/nonempty transitions avoid unrelated selector work while controls still repaint;
    • the existing textarea browser contract is promoted to required.

    Evidence:

    • Chromium 150: css-textarea-dynamic-state.html 6/6;
    • native required profile: 1/1 document, 6/6 subtests;
    • focused 4,096-control gate: 1,000 transitions in 7.80331 ms on exact-head Linux CI, stable V8 heap (816,704 -> 816,704 bytes), bounded RSS (92,598,272 -> 97,316,864 bytes);
    • exact-head Linux document contracts passed.

    The Linux package matrix compiled and executed the new gate, then its broad aggregate failed the same six unrelated tests as the preceding main package run. That baseline comparison is recorded on PR #342.

    This issue remains open for the excluded follow-on pseudo-classes and full constraint-validation slices.

  4. wieslawsoltes commented on Sep 18, 2026

    @wieslawsoltes
    CollaboratorAuthor

    Focused child #446 is complete through PR #447 at merge a263f4e084dd510d9397ba4c9c7c57d44cb255a8 (source 499246522fbb3c5af9d231e23fa211e07a06c4d7, exact base 4ea2feebd0dd7f2f08dfa1a8bfbbe1ca5f3d6c3b).

    The next live form-state slice now matches :required and :optional for applicable input, select, and textarea controls. Missing and unknown input types use text applicability; hidden, range, color, button-like inputs, buttons, and unrelated elements match neither state. Existing bounded required invalidation now also tracks type transitions that change applicability.

    Implementation-only debt remains explicit: browser/WPT/native correctness, build, performance, allocation, memory, lifecycle, scene/pixel, product, hosted checks, and CI monitoring were skipped. Only git diff --check was run. #257 stays open for read-only/read-write, range, checked/indeterminate, disabled/enabled, supported user-valid/user-invalid behavior, broader constraint validation/form ownership/reset, and cumulative validation/product acceptance.

    Consolidation PR #76 was not changed or merged.

  5. wieslawsoltes commented on Sep 18, 2026

    @wieslawsoltes
    CollaboratorAuthor

    Focused child #452 is complete through PR #453 at merge 580f177c18b067bd6b11aef9d7b2b2e400804a0d (source e4ae4c0d30b5b8c7b7e006bc3b432fe0809b905f, rebased base 3813a31772917655f71be8a15b04aeb096a049d8 after #450/#451).

    Native selector matching now derives :read-write from mutable text-capable input/textarea state and inherited contenteditable=true/empty/plaintext-only regions, with contenteditable=false boundaries. Readonly or disabled text controls, non-text controls, and other non-editable elements match :read-only. Dependency metadata covers readonly, type, inherited disabled, inherited contenteditable, and the first-legend structural boundary.

    Implementation-only debt remains explicit: browser/WPT/native correctness, build, performance, allocation, memory, lifecycle, scene/pixel, product, hosted checks, and CI monitoring were skipped. Only git diff --check was run. Document designMode and richer editing-host behavior remain outside this slice. #257 stays open for range, checked/indeterminate, disabled/enabled acceptance, supported user-valid/user-invalid behavior, broader constraint validation/form ownership/reset, and cumulative validation/product acceptance.

    Consolidation PR #76 was not changed or merged.

  6. wieslawsoltes commented on Sep 18, 2026

    @wieslawsoltes
    CollaboratorAuthor

    Focused child #457 is complete through PR #459 at merge 1d663aeb825fd12ac1f9c3822a65a4c53fd07b1f (source 510b77e5cba0d6e5698778a0de9ea9d29d941553, exact base a9f309c8ff80d701ef34e66aece8441e0f8f7fb6).

    WebScene now owns live non-reflected input.indeterminate state in the cold form-control record and exposes it through both DOM binding lanes. Checkbox :indeterminate consumes that state; click activation clears it and canceled activation restores it with checkedness. Radio :indeterminate is derived from the existing live checkedness group, and checked property/native activation changes recascade bounded group members. The native checkbox affordance paints an indeterminate dash, and dependency metadata covers the live state plus checked/type/name and child-list inputs.

    Implementation-only debt remains explicit: browser/WPT/native correctness, binding checks, build, performance, allocation, memory, lifecycle, scene/pixel, product, hosted checks, and CI monitoring were skipped. The generated binding artifact was refreshed from the pinned manifest and git diff --check passed. Complete form-owner/reparenting semantics, shadow-tree edge cases, and <progress>:indeterminate remain outside this slice. #257 stays open for range states, supported user-valid/user-invalid behavior, broader constraint validation/form ownership/reset, and cumulative validation/product acceptance.

    Consolidation PR #76 was not changed or merged.

  7. wieslawsoltes commented on Sep 18, 2026

    @wieslawsoltes
    CollaboratorAuthor

    Focused child #462 is complete through PR #465 at merge b383afc181e4794ef7b7f5266cb8f5d51c6c41b1 (source 231aaf6405a63a781fa708edc73f9cdb5e52b0f1, rebased base d27290970ef4913b89a083da89a220726ee5e29b).

    WebScene now matches :in-range / :out-of-range for finite live input[type=number|range] values against valid min/max bounds. Range controls use 0/100 defaults and an implied midpoint for an empty live value; empty or invalid number values match neither state. min/max are reflected through both DOM binding lanes. A dedicated $live-form-range dependency extends the existing live-value checkpoint so nonempty-to-nonempty property writes, native edits, and resets recascade only when numeric classification changes; type/min/max mutations use the standard attribute path.

    Implementation-only debt remains explicit: browser/WPT/native correctness, binding checks, build, performance, allocation, memory, lifecycle, scene/pixel, product, hosted checks, and CI monitoring were skipped. The generated binding artifact was refreshed from the pinned manifest and git diff --check passed. Date/time/month/week types, step mismatch, bad-input sanitization, full constraint-validation APIs, user-valid/user-invalid, and cumulative acceptance remain open.

    This ends the requested implementation wave. Consolidation PR #76 was not changed or merged.

  8. wieslawsoltes commented on Sep 18, 2026

    @wieslawsoltes
    CollaboratorAuthor

    Implementation-only follow-up merged through child #474 / PR #475 as efe3f3e7bddb67a2a92a173264693a86c2cef4f8.

    This adds complete CSS :default matching for authored checked checkbox/radio inputs, authored selected options, and the first submit-capable control owned by a form, including explicit form ownership and iframe/document isolation. Direct defaults use targeted checked/selected invalidation; the rare submitter ownership/order mutations (type, form, id, child-list) conservatively recascade so the replacement default is never stale.

    Per the implementation-only directive, WPT/browser/native tests, builds, mutation/performance/lifecycle gates, package qualification, and CI monitoring remain explicit debt on #474.

  9. 7 remaining items

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

    vscode-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