Repository navigation
Isolate projects sharing a Service Worker registration #45
Copy link
Copy link
Closed
Description
Summary
- Goal: Run independent projects in different tabs under the same origin and Service Worker scope.
- Current concern: The Service Worker uses a shared virtual filesystem and a single current Web Worker RPC/port, even when different host clients connect.
- Request: Isolate project files, transform requests, and HMR routing by runtime owner while allowing previews of one project to share that project's state.
- Scope: Correct ownership and routing under one registration. No separate origin or Service Worker registration per project should be required.
- Verification status: This is a source-based architecture concern; the two-tab scenario below has not been reproduced in a browser during this review.
Details
Shared state observations, required isolation, and a two-tab acceptance scenario
Current implementation
Reviewed at 03ea7fb. The Service Worker bootstrap uses one imported filesystem and subscriber; incoming V_FS_* messages are applied without selecting a project owner.
The server stores one workerRpc and one swWwPort. A connection supplies a client ID for its acknowledgement, but the active transform/HMR connection is not stored per project.
Per-preview session IDs within one runtime do not by themselves establish isolation between separate runtime owners. Please validate and support that boundary explicitly.
Requested behavior
- Allow two host tabs to use the same registration and identical virtual paths with different file contents.
- Route filesystem mutations, document requests, transforms, and HMR messages to the correct owning project. Include requests initiated by preview iframes and their assets.
- Let multiple preview sessions of one project share its files and updates, while keeping independent projects separate.
- Removing previews or disposing one owner must not replace or remove another owner's files, ports, or subscriptions.
- Define how request ownership is established and validated. Do not rely only on an arbitrary preview ID or whichever Web Worker connected most recently.
Acceptance criteria
- Open two tabs with
/index.htmland/src/main.tsat the same virtual paths but visibly different content. Initialize them in both orders. - Update, add, and delete files in either tab; reload both previews and confirm each sees only its own project.
- Deliver delayed transform responses and HMR events while both tabs edit; responses stay with their owners.
- Close or dispose one owner; the other continues loading assets, editing, and reloading.
- Multiple sessions belonging to one owner still share updates as intended.
Start with the browser regression scenario above, then implement the required routing/state separation. The choice of internal project identity and request transport remains an implementation decision.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
kazupon commentedon Oct 1, 2026
Carrying over acceptance criterion 5 of #43, which #60 did not cover:
This issue already lists the same scenario ("Close or dispose one owner; the other continues loading assets, editing, and reloading"), so it is tracked here.
Since #60, the problem looks like this:
swWwPortandworkerRpc).kazupon commentedon Oct 1, 2026
Carrying over the part of the acceptance criteria of #46 that #72 did not cover:
#72 covers disposal while a recovery is pending. The two-client part depends on the owner separation that this issue asks for, so it is tracked here. The same goes for this request in #46: "Recovery for one client must not replace another client's project."
Since #72, a restart of the Service Worker process is handled like this:
listen()completes, the Service Worker sendsV_SW_INSTANCE_STARTEDwith a new instance ID to every window client it controls (service-worker-core.ts).V_FS_INIT, then connects its Web Worker channel again (index.ts).V_FS_INITand a Web Worker channel, for up to 10 seconds (service-worker-core.ts).When two clients share the registration:
swWwPortandworkerRpc.ready().Notes for the separation:
V_WW_CONNECT_PORTnow carries aruntimeId, created whenready()starts (index.ts). It marks the owner of a channel. The Service Worker does not use it yet.V_FS_*messages carry no owner yet. This issue can decide how to route them: an owner field on each message, or a port per owner.V_WW_CONNECT_PORT_ACKdoes not say which connection it acknowledges, and the Service Worker sends it to the page. If two runtimes in one page connect at the same time, each could take the other's acknowledgement.One more acceptance criterion for this issue:
ServiceWorker.stopAllWorkersof the DevTools Protocol, as inrestart.integration-test.ts. Afterwards, each client's previews load that client's latest files, and the recovery of one client does not replace the project of the other.fix(vrowzer): isolate projects that share a Service Worker registrati…