Skip to content

Implement top-level Location navigation through the native host boundary #270

Closed

Description

@wieslawsoltes

Parent boundary: SceneTech/AppScene#124
Blocked product bootstrap: #252
Picker prerequisite: #247 (completed)

Problem

Unchanged VS Code OSS reuses its browser window after Open Folder... by assigning the generated workspace URL to window.location.href. WebScene currently exposes location as an ordinary object whose href is a writable data property. Assignment changes the JavaScript string but emits no navigation request, runs no beforeunload/pagehide decision, and creates no replacement document. AppScene therefore has no target to admit and reload.

The completed #247 trace retained the exact input:

vscode-remote://127.0.0.1:64170/private/tmp/webscene-247-fixture/beta
forceNewWindow=false forceReuseWindow=false addMode=false

VS Code WorkspaceProvider.open(..., { reuse: true }) converts that to the same-origin target /?folder=/private/tmp/webscene-247-fixture/beta and executes mainWindow.location.href = targetHref.

Reduced root cause

set_context_location in webscene_v8_runtime_document.inc installs href, protocol, host, pathname, search, and hash as ordinary object properties. Only location.reload() has an active operation: it emits WEBSCENE_HOST_REQUEST_WINDOW_RELOAD_V1. There is no setter or assign/replace implementation for top-level URL navigation and no typed same-window navigation request carrying the resolved target.

Scope

  • Implement browser-shaped top-level Location.href assignment plus Location.assign() and Location.replace() URL resolution.
  • Apply the same-origin/scheme and byte-size admission policy before enqueueing a bounded typed request. Keep fragment-only navigation separately observable without replacing the document.
  • Run cancellable beforeunload; only an allowed transition reaches the host. Dispatch pagehide exactly once when the host accepts and loads the replacement document.
  • Add an additive typed native ABI request containing the byte-exact resolved URL and replace/history decision.
  • In AppScene#124, validate the request against the owned loopback origin, record the decision, update the owned document URL, and reload the existing engine/window through load_url_with_viewport.
  • Preserve profile/storage, companion ownership, viewport, diagnostics, and document-start scripts. Reject malformed, cross-origin, oversized, stale, duplicate, and queue-saturated requests without mutating the live URL.

Acceptance

  • Browser oracle: href=, assign(), and replace() resolve relative/query URLs byte-exactly; veto, malformed URL, cross-origin, and fragment cases have matching observable results.
  • Direct WebScene native tests retain the typed target/decision, enforce queue and URL bounds, run beforeunload once, and prove no document generation occurs until the host calls the load API.
  • Direct AppScene tests accept only the owned same-origin loopback target, preserve the existing window/companion, and reject unsupported or stale targets.
  • Two successful A → B → A transitions create fresh realms/documents, emit one pagehide per retired document, and leave no old timers, workers, ports, sockets, host requests, scenes, or queued callbacks.
  • Unchanged VS Code acceptance correlates the Qualify VS Code remote file and folder picker interaction #247 selected URI with target URL, native decision, replacement-document generation, workspace context URI, provider registration, root stat/readdir, Explorer children/rows, and first watcher events.
  • Record cold/warm p50/p95 for request-to-decision, decision-to-new-document, root enumeration, and first Explorer row. Bound typed-request depth, DOM/scene publication, worker/socket/watch counts, CPU, and retained memory across repeated A → B → A cycles.

Do not include window.open/secondary-window behavior; SceneTech/AppScene#41 owns that path. File edit/save/recovery remains #269.

Activity

  1. wieslawsoltes commented on Sep 17, 2026

    @wieslawsoltes
    CollaboratorAuthor

    Implemented by #274 at 7c19a3c7.

    Exact packaged Code OSS evidence retained from the local AppScene dependency candidate:

    • selected URI: vscode-remote://127.0.0.1:50910/private/tmp/webscene-247-fixture/beta
    • top-level target: http://127.0.0.1:50910/?folder=%2Fprivate%2Ftmp%2Fwebscene-247-fixture%2Fbeta&scene-navigation-generation=1
    • native decision: accepted, generation 2, replace false
    • generation-2 load latency: 0.0404 ms
    • new-document diagnostics report the exact target URL

    Direct gate: href/assign/replace, same-origin and 8 KiB admission, FIFO ordering, queue high-water 1,000, and 10,000 requests in 0.015s.

  2. wieslawsoltes commented on Sep 18, 2026

    @wieslawsoltes
    CollaboratorAuthor

    Reopened for the existing native IndexedDB contract integration failure in main NuGet run 35320520086.

    Both Linux and macOS fail immediately at indexeddb-test-origin.js:1 with WebScene rejected the same-window navigation request. The fixture's configure_indexeddb_test_origin() assigns location.protocol, hostname, origin, and finally location.href solely to synthesize an origin. Since #270, location.href= correctly enters the typed same-window navigation boundary; this storage fixture provides no host admission callback, so rejection is expected and the IndexedDB body never runs.

    This is not caused by current 1cf8bc52: closest completed predecessor bea90e8e, run 35288000024, has the byte-identical error on Linux and macOS, while 348ea440..1cf8bc52 changes only macOS SDK audit/package files. Ownership stays here because the stale test-origin setup must use an admitted initial document URL or an explicit #270 host-navigation fixture rather than bypassing active Location semantics. No duplicate regression issue was opened.

  3. wieslawsoltes commented on Sep 18, 2026

    @wieslawsoltes
    CollaboratorAuthor

    Reopened CI ownership is retained in the native hierarchy: this issue is now a sub-issue of its AppScene #124 host-boundary parent, which remains under the AppScene #122 file/workspace epic and WebScene #227 release graph. It carries vscode-oss/planned while the same-window navigation fixture is requalified.

  4. wieslawsoltes commented on Sep 18, 2026

    @wieslawsoltes
    CollaboratorAuthor

    Requalification completed on current main and merged via #352 at cc18b9337374ea6aadc570280d503547f3621497.

    The production contract from #274 remains correct: Location.href, assign(), and replace() resolve same-origin targets, emit bounded typed WINDOW_NAVIGATE requests, retain replace-history intent, and do not mutate the document before native admission. The reopened failure was the IndexedDB test fixture assigning location.href without installing a native host admission boundary. #352 now loads that fixture through webscene_engine_load_url and asserts the exact initial URL plus absence of a script-originated host request.

    Current evidence:

    • Chromium controls: same-origin location.href and location.replace reached their target documents.
    • IndexedDB persistence/quota/corruption filter: pass in 1.25 s; peak RSS 61,652,992 bytes.
    • Typed host isolation: 10,000 same-window navigation requests in 23.0966 ms; queue high-water 1,000; peak RSS 55,492,608 bytes.
    • Navigation lifecycle: 31 realm replacements in 76.0889 ms; heap 1,362,964 bytes before/after; listeners 1 before/after.
    • Close lifecycle: 10,000 native decisions in 114.699 ms and 10,000 script decisions in 4.534 ms; heap 727,560 bytes before/after.
    • PR CI: portable V8, macOS ARM64, Linux X64, metadata, and NativeAOT 11 passed.

    No production WebScene behavior changed. The broad desktop-host filter still has a separate post-navigation V8 fatal on current main; the #270 Location assertions execute before that unrelated failure and the focused navigation/lifecycle filters are green.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions