Skip to content

Commit a493d80

Browse files
chore(mobile): merge upstream for SVG cancellation fix
2 parents 358b891 + 62245d8 commit a493d80

322 files changed

Lines changed: 9339 additions & 5315 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎apps/desktop/src/app/DesktopCliCommand.test.ts‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,15 @@ it.layer(NodeServices.layer)("DesktopCliCommand", (it) => {
100100
const command = yield* commandIn({ home });
101101
const link = path.join(home, ".local", "bin", "t3");
102102

103-
expect(yield* command.state).toEqual({ supported: true, installedPath: null, onPath: false });
103+
expect(yield* command.state).toEqual({
104+
supported: true,
105+
installedPath: null,
106+
onPath: false,
107+
launcherPath: null,
108+
});
104109
const installed = yield* command.install;
105110
expect(installed.installedPath).toBe(link);
111+
expect(installed.launcherPath).toBe(path.join(home, ".t3", "bin", "t3"));
106112
expect(yield* fs.readLink(link)).toBe(path.join(home, ".t3", "bin", "t3"));
107113
expect((yield* command.install).installedPath).toBe(link);
108114

‎apps/desktop/src/app/DesktopCliCommand.ts‎

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,18 +150,26 @@ export const make = Effect.gen(function* () {
150150

151151
const state: DesktopCliCommand["Service"]["state"] = Effect.gen(function* () {
152152
if (!environment.isPackaged) {
153-
return { supported: false, installedPath: null, onPath: false } as const;
153+
return { supported: false, installedPath: null, onPath: false, launcherPath: null } as const;
154154
}
155+
const launcherPath = (yield* exists(launcher)) ? launcher : null;
155156
const installed = yield* installedAt;
156157
const shadowedBy = yield* foreignFirstOnPath;
157158
const shadow = Option.isSome(shadowedBy) ? { shadowedBy: shadowedBy.value } : {};
158159
if (Option.isNone(installed)) {
159-
return { supported: true, installedPath: null, onPath: false, ...shadow };
160+
return { supported: true, installedPath: null, onPath: false, launcherPath, ...shadow };
160161
}
161162
const first = yield* firstOnPath;
162163
const onPath = windows || (Option.isSome(first) && (yield* isOurLink(first.value)));
163-
return { supported: true, installedPath: installed.value, onPath, ...shadow };
164-
}).pipe(Effect.orElseSucceed(() => ({ supported: false, installedPath: null, onPath: false })));
164+
return { supported: true, installedPath: installed.value, onPath, launcherPath, ...shadow };
165+
}).pipe(
166+
Effect.orElseSucceed(() => ({
167+
supported: false,
168+
installedPath: null,
169+
onPath: false,
170+
launcherPath: null,
171+
})),
172+
);
165173

166174
const ensureLauncher = DesktopCliShim.install.pipe(
167175
Effect.provideService(DesktopEnvironment.DesktopEnvironment, environment),

‎apps/desktop/src/preview/CdpRelay.test.ts‎

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ describe("CDP relay", () => {
6565
]);
6666
pending[0]!();
6767
await settle();
68-
expect(send).toHaveBeenNthCalledWith(1, "Page.captureScreenshot", {}, undefined);
69-
expect(send).toHaveBeenNthCalledWith(2, "DOM.enable", {}, "iframe-session");
68+
expect(send).toHaveBeenNthCalledWith(1, "Page.captureScreenshot", {}, undefined, undefined);
69+
expect(send).toHaveBeenNthCalledWith(2, "DOM.enable", {}, "iframe-session", undefined);
7070
expect(written.at(-1)).toEqual({
7171
id: 5,
7272
result: { method: "Page.captureScreenshot" },
@@ -92,7 +92,30 @@ describe("CDP relay", () => {
9292
}),
9393
);
9494
await settle();
95-
expect(send.mock.calls).toEqual([["Runtime.runIfWaitingForDebugger", {}, "iframe-session"]]);
95+
expect(send.mock.calls).toEqual([
96+
["Runtime.runIfWaitingForDebugger", {}, "iframe-session", undefined],
97+
]);
98+
});
99+
100+
// Playwright enables focus emulation on every page it connects to, and Chromium then
101+
// counts the guest as captured: a preview the panel hides keeps its timers unthrottled.
102+
it("acknowledges Playwright's focus emulation without forcing it onto the guest", async () => {
103+
const send = vi.fn(async () => ({}));
104+
const written: Array<Record<string, unknown>> = [];
105+
const relay = createCdpRelayConnection(makeTarget(send), (raw) =>
106+
written.push(JSON.parse(raw)),
107+
);
108+
relay.receive(
109+
JSON.stringify({
110+
id: 1,
111+
method: "Emulation.setFocusEmulationEnabled",
112+
params: { enabled: true },
113+
sessionId: "t3-preview-page",
114+
}),
115+
);
116+
await settle();
117+
expect(written).toEqual([{ id: 1, result: {}, sessionId: "t3-preview-page" }]);
118+
expect(send).not.toHaveBeenCalled();
96119
});
97120

98121
it("routes tab events to the page session once the page is announced", async () => {
@@ -147,7 +170,7 @@ describe("CDP relay extra sessions", () => {
147170
expect(written.find((m) => m["id"] === 4)).toHaveProperty("error");
148171
relay.receive(JSON.stringify({ id: 5, method: "Page.startScreencast", sessionId: extra }));
149172
await settle();
150-
expect(send).toHaveBeenLastCalledWith("Page.startScreencast", {}, undefined);
173+
expect(send).toHaveBeenLastCalledWith("Page.startScreencast", {}, undefined, extra);
151174
written.length = 0;
152175
relay.event("Page.screencastFrame", { data: "x" }, undefined);
153176
expect(written.map((m) => m["sessionId"])).toEqual(["t3-preview-page", extra]);

‎apps/desktop/src/preview/CdpRelay.ts‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ export interface CdpRelayTarget {
55
method: string,
66
params: Record<string, unknown>,
77
sessionId: string | undefined,
8+
/** The extra session that sent it, such as a viewer's; the main connection has none. */
9+
owner?: string,
810
) => Promise<unknown>;
11+
readonly sessionDetached?: (owner: string) => void;
912
/** The page's own CDP target id; Playwright keys the main frame by it. */
1013
readonly targetId: () => Promise<string>;
1114
readonly url: () => string;
@@ -111,8 +114,10 @@ export function createCdpRelayConnection(
111114
}
112115
case "Target.detachFromTarget": {
113116
const sessionId = command.params?.["sessionId"];
114-
if (typeof sessionId === "string" && sessionId !== PAGE_SESSION_ID)
117+
if (typeof sessionId === "string" && sessionId !== PAGE_SESSION_ID) {
115118
sessions.delete(sessionId);
119+
target.sessionDetached?.(sessionId);
120+
}
116121
return {};
117122
}
118123
case "Target.setAutoAttach": {
@@ -133,11 +138,15 @@ export function createCdpRelayConnection(
133138

134139
const pageCommand = (command: CdpCommand): Promise<unknown> => {
135140
const child = sessions.get(command.sessionId!) === "page" ? undefined : command.sessionId;
141+
const owner =
142+
child === undefined && command.sessionId !== PAGE_SESSION_ID ? command.sessionId : undefined;
136143
// Child frames/workers pause on auto-attach until resumed; only the main page can skip this command.
137144
if (command.method === "Runtime.runIfWaitingForDebugger" && child === undefined) {
138145
return Promise.resolve({});
139146
}
140-
return target.send(command.method, command.params ?? {}, child);
147+
// Playwright asks for this on every page; the host emulates focus only while it is in use.
148+
if (command.method === "Emulation.setFocusEmulationEnabled") return Promise.resolve({});
149+
return target.send(command.method, command.params ?? {}, child, owner);
141150
};
142151

143152
return {

0 commit comments

Comments
 (0)