Skip to content

Preserve same-origin iframe WindowProxy through navigation and document replacement #399

Description

@wieslawsoltes

Problem

Unchanged Code OSS creates the Markdown/webview content iframe, navigates it to ./fake.html?<id>, subscribes to DOMContentLoaded through the already-obtained contentWindow, then calls contentDocument.open()/write()/close() to install the real document (vendor/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html:1019-1066).

On exact WebScene main 9378075872bf1a5ebf66a1b1a194bd5cbc5e0614, a native reproduction times out after the fake document loads: the listener registered on the initial frame window never observes the navigated document (lifecycle=0). Chrome 153 completes the sequence and preserves WindowProxy identity.

Focused scope

  • Keep one same-origin iframe WindowProxy identity across the initial about:blank to admitted src navigation.
  • Retain a pre-navigation DOMContentLoaded listener and dispatch it with the navigated contentDocument as target.
  • Support open()/write()/close() on that navigated document so Code OSS can replace fake.html with the supplied Markdown/webview document.
  • Retire navigation listeners, old document/realm handles, and queued lifecycle work when the iframe is removed or replaced.

Security boundary

Keep existing sandbox and same-origin admission checks fail-closed. This leaf does not add cross-origin WindowProxy access, relax CSP/origin/resource admission, change stylesheet/CSSOM behavior, or cover general history/traversal/reload.

Acceptance

  • A Chrome/WPT-derived contract covers WindowProxy identity, event target, fake URL, document replacement, and post-replacement identity.
  • Native reproduces the pre-fix timeout and passes the same assertions after the fix.
  • Unchanged Code OSS Markdown prelude reaches the post-document.close() marker.
  • 100 create/navigate/write/remove cycles leave no stale frame listener/task/document handles and stay within a bounded heap/RSS budget.
  • A 1 MiB replacement payload has bounded completion latency and streaming/copy behavior is measured without weakening resource admission.

Parent: #267
Epic: #264
Program: #227

Activity

  1. wieslawsoltes commented on Sep 18, 2026

    @wieslawsoltes
    CollaboratorAuthor

    Implementation starts from exact main 9378075872bf1a5ebf66a1b1a194bd5cbc5e0614 on feature/iframe-navigation-lifecycle-267.

    Oracle before runtime changes:

    • Chrome 153: 5/5 assertions pass for stable WindowProxy, navigated DOMContentLoaded target/URL, document replacement, and identity after replacement.
    • Native: times out with {"complete":false,"lifecycle":0,...} because the listener registered through the provisional contentWindow is not delivered after hydration.

    Owned paths are limited to iframe/window/document lifecycle runtime files plus focused contracts/native tests. Collision boundary: no CSS root/style/CSSOM paths owned by #393, no resource-admission/origin/CSP relaxation, no cross-origin proxy access, and no general traversal/reload work.

  2. wieslawsoltes commented on Sep 18, 2026

    @wieslawsoltes
    CollaboratorAuthor

    Merged in #402 at 51f71381bda9015b64cf0566534e209f8bfa9986.

    Final evidence:

    • Chrome 153 oracle: 6/6 for stable WindowProxy, navigated DOMContentLoaded, fake URL visibility, document.open/write/close, replacement-script parent reachability, and identity after replacement.
    • Focused native gate: 100 create/navigate/write/remove cycles, p95 3.176 ms, heap 1,359,228 -> 1,359,228 bytes, RSS 40.9 -> 89.9 MiB; listener inventory returns empty.
    • Same-origin replacement and Markdown bootstrap advancement pass; opaque/cross-origin frames expose neither document nor owner-realm capabilities.
    • Exact-head PR checks passed: Linux X64, macOS ARM64, portable V8, native Linux document contracts, NativeAOT Avalonia 11 and 12. NuGet packaging was intentionally canceled as unrelated.
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