












@@ -140,6 +140,7 @@ export async function snapshotAriaViaPlaywright(opts: {
140140cdpUrl: string;
141141targetId?: string;
142142limit?: number;
143+timeoutMs?: number;
143144ssrfPolicy?: SsrFPolicy;
144145}): Promise<{ nodes: AriaSnapshotNode[] }> {
145146const limit = Math.max(1, Math.min(2000, Math.floor(opts.limit ?? 500)));
@@ -157,7 +158,11 @@ export async function snapshotAriaViaPlaywright(opts: {
157158targetId: opts.targetId,
158159});
159160}
160-const res = (await withPageScopedCdpClient({
161+const ariaTimeoutMs =
162+typeof opts.timeoutMs === "number" && Number.isFinite(opts.timeoutMs) && opts.timeoutMs > 0
163+ ? Math.max(500, Math.min(60_000, Math.floor(opts.timeoutMs)))
164+ : undefined;
165+const collectAxTree = withPageScopedCdpClient({
161166cdpUrl: opts.cdpUrl,
162167 page,
163168targetId: opts.targetId,
@@ -167,7 +172,23 @@ export async function snapshotAriaViaPlaywright(opts: {
167172nodes?: RawAXNode[];
168173};
169174},
170-})) as {
175+});
176+const res = (await (ariaTimeoutMs === undefined
177+ ? collectAxTree
178+ : (() => {
179+let timer: ReturnType<typeof setTimeout> | undefined;
180+const timeout = new Promise<never>((_, reject) => {
181+timer = setTimeout(() => {
182+reject(new Error(`Aria snapshot via Playwright timed out after ${ariaTimeoutMs}ms.`));
183+}, ariaTimeoutMs);
184+timer.unref?.();
185+});
186+return Promise.race([collectAxTree, timeout]).finally(() => {
187+if (timer) {
188+clearTimeout(timer);
189+}
190+});
191+})())) as {
171192nodes?: RawAXNode[];
172193};
173194const nodes = Array.isArray(res?.nodes) ? res.nodes : [];
@@ -241,6 +262,7 @@ export async function snapshotRoleViaPlaywright(opts: {
241262refsMode?: "role" | "aria";
242263options?: RoleSnapshotOptions;
243264urls?: boolean;
265+timeoutMs?: number;
244266ssrfPolicy?: SsrFPolicy;
245267}): Promise<{
246268snapshot: string;
@@ -262,13 +284,15 @@ export async function snapshotRoleViaPlaywright(opts: {
262284});
263285}
264286287+const ariaSnapshotTimeout = Math.max(500, Math.min(60_000, Math.floor(opts.timeoutMs ?? 5000)));
288+265289if (opts.refsMode === "aria") {
266290if (normalizeOptionalString(opts.selector) || normalizeOptionalString(opts.frameSelector)) {
267291throw new Error("refs=aria does not support selector/frame snapshots yet.");
268292}
269293const snapshot = await page.ariaSnapshot({
270294mode: "ai",
271-timeout: 5000,
295+timeout: ariaSnapshotTimeout,
272296});
273297const built = buildRoleSnapshotFromAiSnapshot(snapshot, opts.options);
274298const snapshotWithUrls = opts.urls
@@ -298,7 +322,7 @@ export async function snapshotRoleViaPlaywright(opts: {
298322 ? page.locator(selector)
299323 : page.locator(":root");
300324301-const ariaSnapshot = await locator.ariaSnapshot();
325+const ariaSnapshot = await locator.ariaSnapshot({ timeout: ariaSnapshotTimeout });
302326const built = buildRoleSnapshotFromAriaSnapshot(ariaSnapshot ?? "", opts.options);
303327const snapshotWithUrls = opts.urls
304328 ? appendSnapshotUrls(built.snapshot, await collectSnapshotUrls(page))
此內容由慣性聚合(RSS閱讀器)自動聚合整理,僅供閱讀參考。 原文來自 — 版權歸原作者所有。