fix(viewer): keep rich parts visible under Chrome 149 field trials#101
fix(viewer): keep rich parts visible under Chrome 149 field trials#101kiluazen wants to merge 1 commit into
Conversation
|
While digging into this on an affected machine (
So the field trial defers layout only for opaque-origin srcdoc iframes; same-origin frames lay out synchronously. That explains why a fixed-time bridge (and the single re-parse retry) miss it intermittently — layout can land after the last timer, and re-parsing just opens a new race window. This backoff-retry PR is still a strict improvement to the existing workaround, but flagging the root finding in case it informs a more decisive fix (e.g. a non-opaque but still-isolated rendering path, or gating on the trial). Obviously |
056c8e6 to
a5c8d8c
Compare
a5c8d8c to
4fcf3d5
Compare
Chrome 149 field-trial variants can defer layout in opaque-origin srcdoc frames, leaving rich surfaces blank or clipped even after the existing reparse retry. Render rich srcdoc frames same-origin to avoid the affected layout path and replace unsafe-inline with a fresh per-document CSP nonce. Only the trusted resize and interaction bridge receives the nonce; rendered part bodies remain non-executable. Move code-part copy behavior into that bridge so code surfaces remain functional under the stricter policy. Add browser coverage proving injected scripts and handlers stay blocked while the bridge and code-copy path work.
4fcf3d5 to
1366d21
Compare
|
@kiluazen Thanks for opening this, taking a look. First reaction: activating |
|
Opened #125 as an alternative that keeps the opaque origin. It loads rich frames from a The key open question for both PRs: is the bug specific to opaque-origin |
Problem
Rich parts (markdown, diff, terminal, mermaid, code, and comments) can render blank or clipped on every reload in affected Chrome 149 field-trial variants. The failure is non-deterministic per frame: the same surface may appear on one refresh and disappear on the next.
Root-cause evidence
Rich parts use sandboxed
srcdociframes. On an affected Chrome profile, opaque-origin frames defer layout:scrollHeight,offsetHeight, andgetBoundingClientRect()return zero when the bridge measures them. Off-screen frames may never produce a later resize, so the viewer leaves them collapsed.The same 500px document produces different measurements solely from the sandbox mode:
loadallow-scripts(opaque origin)allow-scripts allow-same-originThis isolates the browser trigger to opaque-origin
srcdoclayout. The exact upstream Chrome experiment is still unidentified; disabling field trials on the same Chrome binary removes the failure. The single delayed reparse from #85 is not deterministic because it starts another layout race.Fix
srcdocframes withsandbox="allow-scripts allow-same-origin", avoiding the affected opaque-origin layout path.script-src 'unsafe-inline'withscript-src 'nonce-<value>'; only the trusted resize/interaction bridge receives the nonce./s/:idunchanged; they remain opaque-origin and intentionally support scripts.Security boundary
This deliberately changes rich-frame containment from an opaque origin to a nonce-only script policy because the opaque-origin
srcdocpath is the browser trigger. CSP is therefore load-bearing for rich frames.Behavioral browser coverage now feeds unsanitized
<script>andonerrormarkup directly into a rich document and verifies that:The policy still has no
connect-src, CDN script source,'unsafe-inline', or board-origin script source.Validation
npm test— 192/192 passnpm run typecheck— pass (Node, Workers, viewer)npm run lint— passnpm run format:check— passSupersedes this PR's earlier retry/backoff implementation.