LearnNewsExamplesServices
Frontmatter
id17895
titleDock FLIP capture/play omit windowId, routing to the first port
stateClosed
labels
bugai
assigneesneo-opus-vega
createdAtAug 31, 2026, 12:26 AM
updatedAtAug 31, 2026, 1:16 AM
githubUrlhttps://github.com/neomjs/neo/issues/17895
authorneo-opus-vega
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 31, 2026, 1:14 AM

Dock FLIP capture/play omit windowId, routing to the first port

neo-opus-vega
neo-opus-vega commented on Aug 31, 2026, 12:26 AM

Context

Booting a SharedWorkers dock workspace (private client repo) prints two warnings in the app worker before any interaction: sendMessage destination "main" is deprecated. Use a windowId instead. A race-free CDP attach (browser-level auto-attach, waitForDebuggerOnStart) captured the live argument previews: both are remote-method calls with remoteClassName=Neo.main.addon.DockFlip, remoteMethod=captureFirst / play, destination=main.

Live latest-open sweep: checked latest 20 open issues at 2026-08-30T22:15Z; no equivalent found. Prior art: #8149 migrated messaging to explicit window ids and introduced this deprecation; #8366 fixed the same class of warning for registerRemote.

The Problem

src/dashboard/dock/Workspace.mjs calls the FLIP addon without a windowId:

  • line 1587: flip?.captureFirst({hostId: host.id, markerPrefix: flipMarkerPrefix})
  • line 1654: flip.play({hostId: host.id, markerPrefix: flipMarkerPrefix, geometryOnly: ...})

RemoteMethodAccess#generateRemote swaps the destination to data.windowId only when the caller provides it; absent, the destination stays the deprecated 'main' string and the SharedWorker port cascade falls through to the last-resort first port (worker/Base.mjs#sendMessage JSDoc).

Consequences by topology:

  • Single window (today): works by accident — the first port IS the only window — plus two deprecation warnings on every boot, in every consumer's console.
  • Multi window (tear-out / popup roadmap, old cross-window drag demos): the FLIP capture and play address the FIRST connected window's main thread, not the window whose DOM hosts the dock — a silent wrong-realm no-op at best.

The Architectural Reality

Neo.main.addon.DockFlip is a per-window main-thread addon; its methods operate on THEIR window's DOM and read no windowId from data (grep receipt: no windowId in src/main/addon/DockFlip.mjs). The field is pure routing. The exact realm owning the captured markers is the dock host component's window — host.windowId — which refreshDockWorkspace already has in hand.

The Fix

Add windowId: host.windowId to both payloads in refreshDockWorkspace (src/dashboard/dock/Workspace.mjs:1587 and :1654).

Decision Record impact: none (conforms to the routing contract #8149 established).

Acceptance Criteria

  • AC-1: both DockFlip payloads carry windowId: host.windowId; a unit spec on the workspace seam proves the payload shape (stubbed Neo.main.addon.DockFlip capturing call args).
  • AC-2: booting a SharedWorkers dock app emits zero destination "main" is deprecated warnings from DockFlip calls — receipt from the CDP instrument or an equivalent browser-plane check.
  • AC-3: full unit suite green in fully-parallel mode.

Out of Scope

  • Any DockFlip addon-side change — the addon is realm-correct once routing is.
  • The deprecation warning mechanism itself (worker/Base.mjs#sendMessage), and other no-windowId callers outside the dock namespace (none fire on the observed boot path).

Related

#8149 (windowId migration, prior art), #8366 (registerRemote precedent), #13158 (QT-parity docking epic), #17836 (v13.2 dock rebuild — the code's origin), #17885/#17891 (the client-workspace investigation this fell out of).

Origin Session ID: b51135ac-ec45-4689-ac45-0e99fb073069 Retrieval Hint: "DockFlip windowId first-port routing deprecation"