Skip to content

Commit 3e25b85

Browse files
committed
fix(webui): route the terminal's font wait through the browser platform
The workspace panel reached for `document` directly to wait for the fonts before it measured the terminal's grid. The dependency rules confine that global to the platform layer, and the platform is where the wait belongs: a component that reaches for `document` itself is a component that can only be placed against a browser. The browser platform now owns the wait (`whenFontsReady`), and the panel asks for it the way it asks for every other browser capability. This is the baseline's own `check:webui-dependency` failure — the gate reported these two accesses on the untouched `webui` branch.
1 parent e2de9a1 commit 3e25b85

2 files changed

Lines changed: 26 additions & 2 deletions

File tree

‎packages/webui/src/client/features/workspace/ui/WorkspacePanels.tsx‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,12 @@ export function WebuiWorkspacePanel({ state, dispatch, sessionId, workspaceDir,
525525
terminal.open(host);
526526
let disposed = false;
527527
let initialFitFrame: number | undefined;
528-
void document.fonts.ready.then(() => {
528+
// The grid is measured once the fonts have landed: a measurement taken
529+
// against fallback glyphs is a measurement of the wrong grid. The wait
530+
// comes from the browser platform, because a panel that reached for
531+
// `document` itself would be a panel that could only be placed against a
532+
// browser.
533+
void dom.whenFontsReady().then(() => {
529534
if (disposed) return;
530535
initialFitFrame = requestAnimationFrame(() => {
531536
if (disposed) return;
@@ -570,7 +575,7 @@ export function WebuiWorkspacePanel({ state, dispatch, sessionId, workspaceDir,
570575
const input = terminal.onData((data) => { if (terminalOwner?.canWrite) void terminalOwner.write(terminalId, data); });
571576
let disposed = false;
572577
let initialFitFrame: number | undefined;
573-
void document.fonts.ready.then(() => {
578+
void dom.whenFontsReady().then(() => {
574579
if (disposed) return;
575580
initialFitFrame = requestAnimationFrame(() => {
576581
if (disposed) return;

‎packages/webui/src/client/platform/browser-dom.ts‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,20 @@ export interface WebuiBrowserDom {
101101
* palette.
102102
*/
103103
readonly readCssVariable: (name: string, fallback: string) => string;
104+
/**
105+
* Resolves once the document's fonts have loaded.
106+
*
107+
* A terminal measures its grid after the fonts land: a measurement taken
108+
* against fallback glyphs is a measurement of the wrong grid, and the shell
109+
* that follows it resizes to a size the terminal never had. The wait
110+
* belongs to the platform for the same reason the resize listener does — a
111+
* component that reaches for `document` directly is a component that cannot
112+
* be placed against anything but a browser.
113+
*
114+
* A platform with no document resolves at once: there are no fonts to wait
115+
* for, so the caller measures the grid it has.
116+
*/
117+
readonly whenFontsReady: () => Promise<void>;
104118
/**
105119
* Creates a drawing surface.
106120
*
@@ -223,6 +237,11 @@ export function createWebuiBrowserDom(
223237
.trim();
224238
return value || fallback;
225239
},
240+
whenFontsReady: () => {
241+
const fonts = documentObject?.fonts;
242+
if (!fonts) return Promise.resolve();
243+
return fonts.ready.then(() => undefined);
244+
},
226245
createCanvas: (width, height) => {
227246
if (!documentObject) return null;
228247
const canvas = documentObject.createElement("canvas");

0 commit comments

Comments
 (0)