Skip to content

Implement same-document History state and URL mutation #392

Description

@wieslawsoltes

Parent: #267
Top-level epics: #264, #227

Reproduction

The pinned unchanged Code OSS Markdown fixture prepares its packaged file: URL with:

const prepared = new URL(location.href);
prepared.searchParams.set('id', 'markdown-preview');
history.replaceState(null, '', prepared);

At WebScene d4dc4fc1, history.pushState and history.replaceState are inert no-ops. location.href therefore remains unchanged, the fixture falls through to location.replace(next), and the native focused runtime rejects that host navigation before the ServiceWorker/resource and nested-document phases can run. Chrome updates the current entry and live Location/Document URL without performing a document navigation.

Scope and proposed fix

Implement reusable same-document History state/URL mutation for the top-level realm and every fully created same-origin realm. Actual iframe navigation/WindowProxy construction remains in #267 and will provide the end-to-end nested-frame exercise:

  • real pushState(state, unused, url?) and replaceState(state, unused, url?) argument, URL resolution, same-origin and bounded-input behavior;
  • live history.state, history.length, and Location/Document URL/base reflection without a host navigation or realm replacement;
  • browser-compatible SecurityError and DataCloneError behavior for invalid/cross-origin URLs and uncloneable state;
  • stable Location/History identity and stale-realm rejection;
  • retain strict separation from Location.assign/replace, full-document navigation, native host authority, CSP, ServiceWorker, resource admission, filesystem, and network permissions.

History traversal (back/forward/go) should be implemented here only if the selected reference tests require it for correctness; otherwise keep it as the next focused #267 child with explicit coverage.

Acceptance

  • Checked-in Chromium/WPT-derived contract covers omitted/relative/absolute same-origin URLs, query/fragment updates, state, length, stable object identity, invalid/cross-origin rejection, receiver branding, and no popstate on the initiating call.
  • Native top-level and exact pinned file: URL-object contracts match the oracle, update location.href/search/hash, document.URL/documentURI/baseURI, and resolve subsequent relative resources against the updated document URL. History is installed for frame realms when Enforce secure nested-document lifecycle for Code OSS webviews #267 constructs them; end-to-end iframe navigation remains there.
  • The unchanged pinned Markdown fixture advances past its id=markdown-preview preparation without a host navigation request.
  • 10,000 replace operations and 1,000 bounded push operations publish no layout/scene work, meet p95 <= 0.25 ms, keep queues bounded, and retain <= 2 MiB RSS after warm-up.
  • Repeated mutation and adjacent 31-cycle navigation-realm teardown retain stable heap/listener counts; full nested-frame retirement stays with Enforce secure nested-document lifecycle for Code OSS webviews #267.
  • Linux, macOS, portable V8, native document, sanitizer, and selected Chrome/WPT gates pass.

Collision audit

This owns the History bindings, same-document URL/base update helpers, and focused contracts. It does not overlap active #382 IndexedDB/File System paths, #386 CSSOM paths, #388 resource-only tests, or consolidation #76. The broader #267 stack retains iframe navigation, WindowProxy, document open/write/close, CSP/Permissions Policy, replacement, traversal if deferred, and teardown acceptance.

Activity

  1. wieslawsoltes commented on Sep 18, 2026

    @wieslawsoltes
    CollaboratorAuthor

    Implementation is open in #396 at bd3a927e.

    Focused evidence before opening the PR:

    • Chrome 153 contract: 6/6
    • native contract: 6/6
    • 10,000 replaceState + 1,000 bounded pushState: p95 about 0.01 ms, zero layout/scene publications
    • exact Code OSS Markdown file: URL-object path updates in place and emits no host navigation request
    • adjacent navigation-realm teardown: 31 cycles with stable heap/listener counts
    • adjacent Markdown resource broker performance/memory gate passes

    The issue body now separates this same-document primitive from #267's remaining iframe navigation/WindowProxy construction and traversal work. Direct PR runners are pending; the package publication workflow is intentionally canceled for this focused runtime change.

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