Skip to content

The app's component runs inside the frame - #148

Merged
lannbot merged 1 commit into
mainfrom
frame/instance-in-frame
Sep 5, 2026
Merged

The app's component runs inside the frame#148
lannbot merged 1 commit into
mainfrom
frame/instance-in-frame

Conversation

@lannbot

@lannbot lannbot commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator

Step B of #142's design; step A was #147. mountApp keeps its shape, its internals change, no caller changed.

frame.js: 3 KB → 192 KB raw / 58 KB gzip, as spike 2 predicted.

Gates: deno check both consumers; check-invariants.sh 9/9 (seam scans now mount.ts + frame.ts + frame.html); spikes/todomvc e2e 5/5; demo e2e 36/36, zero scenario edits; direct probe in Chromium and Firefox (12/12).

Out of scope: the dioxus dialect's spike transport (until polyengine-dioxus's host runs in this frame runtime); where a framed app's route lives; a linker-side async-lowering check. Comments in spikes/todomvc/{host/dioxus-frame.ts,README.md,e2e/tests/dioxus-frame.spec.ts} still name frame-backend.ts; repoint with the dioxus follow-up.

Automerge armed.

mountApp keeps its shape; its internals change. frame.ts is now the
in-frame runtime: on the one mount message from its embedder it
instantiates the guest with polyengine in the frame's own realm, binds
polyvisor:surface to that document's real DOM through the existing
createDirectBackend (synchronously — no op array, no structured clone,
no second validation pass), and serves the visor's calls into the
guest's exports over a control port. Every OTHER import the app is
granted is a proxy over its own MessagePort back to the visor-side
implementation, with WIT errors crossing as @polyengine/protocol's
cloneable form so a host `result` err arrives in the guest as
err(payload), not a trap. The queued op protocol leaves the app path;
frame-backend.ts is deleted. The applier and the queued/channel
backends stay: the todomvc harness is their instrument, and the
applier's re-validation is still what a trusted-territory backend
needs.

The frame's policy becomes the ruled one (#142, spikes 3–4):
sandbox="allow-scripts allow-forms" — without allow-forms the submit
event never fires at all, so <form onsubmit> is dead — and a meta CSP
of default-src 'none' with the script hash, 'wasm-unsafe-eval' (the
guest is compiled here now), img-src blob: data:, font-src blob:,
media-src blob:, form-action 'none'. A form-action violation is an app
that forgot preventDefault and is logged; every other violation is a
fault. Suspension is two halves because neither suffices (#142 P1):
`inert` on the iframe, and in the frame the runner's gate plus
dropping focus. Height comes from a ResizeObserver. The mount message
is accepted once and only from window.parent — sibling frames can
reach this one's WindowProxy — with the transferred ports as the real
authenticator.

Linker rule this rests on, recorded in NOTES: an import that crosses a
realm must be async-declared in the WIT. The guest then suspends
through the component model's async ABI and the frame needs no JSPI —
Firefox 144, which has none, runs the in-frame guest.

No caller changed. frame.js grows from ~3 KB to 192 KB raw / 58 KB
gzip (it carries the embedder), as spike 2 predicted.

Gates: deno check (demo, spikes/todomvc); check-invariants 9/9, its
seam scans now covering mount.ts + frame.ts + frame.html;
spikes/todomvc e2e 5/5; demo e2e 36/36 with zero scenario edits; a
direct probe in Chromium and Firefox (srcdoc, sandbox flags, the meta
directives, in-frame fetch never reaching the server, a typed todo,
inert on suspend, iframe gone on destroy).

Out of scope, deliberately: the dioxus dialect's spike transport
(spikes/todomvc/host/dioxus-frame.ts) stays until polyengine-dioxus's
host runs in this frame runtime; where a framed app's route lives; a
linker-side check that cross-realm imports are async-lowered.
@lannbot
lannbot enabled auto-merge September 5, 2026 19:58
@lannbot
lannbot merged commit 71b5c72 into main Sep 5, 2026
3 checks passed
@lannbot
lannbot deleted the frame/instance-in-frame branch September 5, 2026 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant