@opensteer/engine-playwright 0.8.1 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1259,6 +1259,282 @@ function sleep(ms) {
1259
1259
  return new Promise((resolve) => setTimeout(resolve, ms));
1260
1260
  }
1261
1261
 
1262
+ // ../browser-core/src/post-load-tracker.ts
1263
+ var DEFAULT_POST_LOAD_TRACKER_QUIET_WINDOW_MS = 400;
1264
+ var DEFAULT_ACTION_BOUNDARY_POLL_INTERVAL_MS = 100;
1265
+ function isRecord(value) {
1266
+ return typeof value === "object" && value !== null;
1267
+ }
1268
+ function readFiniteNumber(value) {
1269
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1270
+ }
1271
+ function readNonNegativeNumber(value) {
1272
+ const parsed = readFiniteNumber(value);
1273
+ return parsed === void 0 || parsed < 0 ? 0 : parsed;
1274
+ }
1275
+ function normalizePostLoadTrackerState(value) {
1276
+ if (!isRecord(value)) {
1277
+ return void 0;
1278
+ }
1279
+ const installedAt = readFiniteNumber(value.installedAt);
1280
+ const lastMutationAt = readFiniteNumber(value.lastMutationAt);
1281
+ const lastNetworkActivityAt = readFiniteNumber(value.lastNetworkActivityAt);
1282
+ const now = readFiniteNumber(value.now);
1283
+ const readyState = typeof value.readyState === "string" ? value.readyState : void 0;
1284
+ if (installedAt === void 0 || lastMutationAt === void 0 || lastNetworkActivityAt === void 0 || now === void 0 || readyState === void 0) {
1285
+ return void 0;
1286
+ }
1287
+ return {
1288
+ installedAt,
1289
+ lastMutationAt,
1290
+ lastNetworkActivityAt,
1291
+ now,
1292
+ pendingFetches: readNonNegativeNumber(value.pendingFetches),
1293
+ pendingTimeouts: readNonNegativeNumber(value.pendingTimeouts),
1294
+ pendingXhrs: readNonNegativeNumber(value.pendingXhrs),
1295
+ readyState
1296
+ };
1297
+ }
1298
+ function buildPostLoadTrackerInstallScript() {
1299
+ return `(() => {
1300
+ const globalObject = globalThis;
1301
+ if (globalObject.__opensteerActionBoundaryTrackerInstalled) {
1302
+ return true;
1303
+ }
1304
+
1305
+ const tracker = {
1306
+ installedAt: performance.now(),
1307
+ lastMutationAt: performance.now(),
1308
+ lastNetworkActivityAt: performance.now(),
1309
+ pendingFetches: 0,
1310
+ pendingTimeouts: 0,
1311
+ pendingXhrs: 0,
1312
+ readyState: document.readyState,
1313
+ timeoutIds: new Set(),
1314
+ };
1315
+ globalObject.__opensteerActionBoundaryTrackerInstalled = true;
1316
+ globalObject.__opensteerActionBoundaryTracker = tracker;
1317
+
1318
+ const markMutation = () => {
1319
+ tracker.lastMutationAt = performance.now();
1320
+ tracker.readyState = document.readyState;
1321
+ };
1322
+ const markNetwork = () => {
1323
+ tracker.lastNetworkActivityAt = performance.now();
1324
+ tracker.readyState = document.readyState;
1325
+ };
1326
+
1327
+ const startObserver = () => {
1328
+ const target = document.documentElement ?? document;
1329
+ if (!(target instanceof Node)) {
1330
+ return;
1331
+ }
1332
+ const observer = new MutationObserver(markMutation);
1333
+ observer.observe(target, {
1334
+ subtree: true,
1335
+ childList: true,
1336
+ characterData: true,
1337
+ attributes: true,
1338
+ });
1339
+ markMutation();
1340
+ };
1341
+
1342
+ if (document.documentElement) {
1343
+ startObserver();
1344
+ } else {
1345
+ document.addEventListener("DOMContentLoaded", startObserver, { once: true });
1346
+ }
1347
+
1348
+ document.addEventListener("readystatechange", markMutation);
1349
+ addEventListener("load", markMutation, { once: true });
1350
+
1351
+ const nativeSetTimeout = globalObject.setTimeout.bind(globalObject);
1352
+ const nativeClearTimeout = globalObject.clearTimeout.bind(globalObject);
1353
+ globalObject.setTimeout = function(callback, delay, ...args) {
1354
+ tracker.pendingTimeouts += 1;
1355
+ markNetwork();
1356
+ let handle;
1357
+ const wrapped =
1358
+ typeof callback === "function"
1359
+ ? (...callbackArgs) => {
1360
+ if (tracker.timeoutIds.delete(handle)) {
1361
+ tracker.pendingTimeouts = Math.max(0, tracker.pendingTimeouts - 1);
1362
+ }
1363
+ try {
1364
+ return callback(...callbackArgs);
1365
+ } finally {
1366
+ markMutation();
1367
+ }
1368
+ }
1369
+ : callback;
1370
+ handle = nativeSetTimeout(wrapped, delay, ...args);
1371
+ tracker.timeoutIds.add(handle);
1372
+ return handle;
1373
+ };
1374
+ globalObject.clearTimeout = function(handle) {
1375
+ if (tracker.timeoutIds.delete(handle)) {
1376
+ tracker.pendingTimeouts = Math.max(0, tracker.pendingTimeouts - 1);
1377
+ }
1378
+ return nativeClearTimeout(handle);
1379
+ };
1380
+
1381
+ if (typeof globalObject.fetch === "function") {
1382
+ const nativeFetch = globalObject.fetch.bind(globalObject);
1383
+ globalObject.fetch = (...args) => {
1384
+ tracker.pendingFetches += 1;
1385
+ markNetwork();
1386
+ return nativeFetch(...args)
1387
+ .finally(() => {
1388
+ tracker.pendingFetches = Math.max(0, tracker.pendingFetches - 1);
1389
+ markNetwork();
1390
+ });
1391
+ };
1392
+ }
1393
+
1394
+ if (typeof globalObject.XMLHttpRequest === "function") {
1395
+ const NativeXMLHttpRequest = globalObject.XMLHttpRequest;
1396
+ const nativeSend = NativeXMLHttpRequest.prototype.send;
1397
+ NativeXMLHttpRequest.prototype.send = function(...args) {
1398
+ tracker.pendingXhrs += 1;
1399
+ markNetwork();
1400
+ const finalize = () => {
1401
+ this.removeEventListener("loadend", finalize);
1402
+ tracker.pendingXhrs = Math.max(0, tracker.pendingXhrs - 1);
1403
+ markNetwork();
1404
+ };
1405
+ this.addEventListener("loadend", finalize, { once: true });
1406
+ return nativeSend.apply(this, args);
1407
+ };
1408
+ }
1409
+
1410
+ return true;
1411
+ })()`;
1412
+ }
1413
+ function buildPostLoadTrackerReadExpression() {
1414
+ return `(() => {
1415
+ const tracker = globalThis.__opensteerActionBoundaryTracker;
1416
+ if (!tracker) {
1417
+ return null;
1418
+ }
1419
+
1420
+ return {
1421
+ installedAt: Number(tracker.installedAt ?? 0),
1422
+ lastMutationAt: Number(tracker.lastMutationAt ?? 0),
1423
+ lastNetworkActivityAt: Number(tracker.lastNetworkActivityAt ?? 0),
1424
+ now: Number(performance.now()),
1425
+ pendingFetches: Number(tracker.pendingFetches ?? 0),
1426
+ pendingTimeouts: Number(tracker.pendingTimeouts ?? 0),
1427
+ pendingXhrs: Number(tracker.pendingXhrs ?? 0),
1428
+ readyState: String(document.readyState),
1429
+ };
1430
+ })()`;
1431
+ }
1432
+ function postLoadTrackerIsSettled(tracker, quietWindowMs = DEFAULT_POST_LOAD_TRACKER_QUIET_WINDOW_MS) {
1433
+ if (!tracker) {
1434
+ return false;
1435
+ }
1436
+ if (tracker.readyState !== "complete") {
1437
+ return false;
1438
+ }
1439
+ if (tracker.pendingFetches > 0 || tracker.pendingTimeouts > 0 || tracker.pendingXhrs > 0) {
1440
+ return false;
1441
+ }
1442
+ const lastActivityAt = Math.max(
1443
+ tracker.installedAt,
1444
+ tracker.lastMutationAt,
1445
+ tracker.lastNetworkActivityAt
1446
+ );
1447
+ return tracker.now - lastActivityAt >= quietWindowMs;
1448
+ }
1449
+
1450
+ // ../browser-core/src/action-boundary.ts
1451
+ var CROSS_DOCUMENT_INTERACTION_TIMEOUT_MS = 3e4;
1452
+ var CROSS_DOCUMENT_DETECTION_WINDOW_MS = 500;
1453
+ async function waitForActionBoundary(input) {
1454
+ if (input.timeoutMs <= 0) {
1455
+ return {
1456
+ trigger: "dom-action",
1457
+ crossDocument: false,
1458
+ bootstrapSettled: false,
1459
+ timedOutPhase: "bootstrap"
1460
+ };
1461
+ }
1462
+ const deadline = Date.now() + input.timeoutMs;
1463
+ const crossDocumentDetectionDeadline = input.snapshot === void 0 ? void 0 : Math.min(deadline, Date.now() + CROSS_DOCUMENT_DETECTION_WINDOW_MS);
1464
+ const pollIntervalMs = input.pollIntervalMs ?? DEFAULT_ACTION_BOUNDARY_POLL_INTERVAL_MS;
1465
+ let trigger = "dom-action";
1466
+ let crossDocument = false;
1467
+ let waitedForNavigationContentLoaded = false;
1468
+ while (Date.now() < deadline) {
1469
+ input.throwBackgroundError();
1470
+ if (input.isPageClosed()) {
1471
+ return {
1472
+ trigger,
1473
+ crossDocument,
1474
+ bootstrapSettled: true
1475
+ };
1476
+ }
1477
+ if (input.signal?.aborted) {
1478
+ if (isTimeoutAbort(input.signal.reason) && Date.now() >= deadline) {
1479
+ return {
1480
+ trigger,
1481
+ crossDocument,
1482
+ bootstrapSettled: false,
1483
+ timedOutPhase: "bootstrap"
1484
+ };
1485
+ }
1486
+ throw abortError(input.signal);
1487
+ }
1488
+ const currentDocumentRef = input.getCurrentMainFrameDocumentRef();
1489
+ if (input.snapshot !== void 0 && currentDocumentRef !== void 0 && currentDocumentRef !== input.snapshot.documentRef) {
1490
+ trigger = "navigation";
1491
+ crossDocument = true;
1492
+ if (!waitedForNavigationContentLoaded) {
1493
+ waitedForNavigationContentLoaded = true;
1494
+ const remaining = Math.max(0, deadline - Date.now());
1495
+ if (remaining > 0) {
1496
+ await input.waitForNavigationContentLoaded(remaining);
1497
+ }
1498
+ }
1499
+ }
1500
+ if (!crossDocument && crossDocumentDetectionDeadline !== void 0 && Date.now() >= crossDocumentDetectionDeadline) {
1501
+ return {
1502
+ trigger,
1503
+ crossDocument,
1504
+ bootstrapSettled: true
1505
+ };
1506
+ }
1507
+ if (crossDocument && postLoadTrackerIsSettled(await input.readTrackerState())) {
1508
+ return {
1509
+ trigger,
1510
+ crossDocument,
1511
+ bootstrapSettled: true
1512
+ };
1513
+ }
1514
+ await delay(Math.min(pollIntervalMs, Math.max(0, deadline - Date.now())));
1515
+ }
1516
+ return {
1517
+ trigger,
1518
+ crossDocument,
1519
+ bootstrapSettled: false,
1520
+ timedOutPhase: "bootstrap"
1521
+ };
1522
+ }
1523
+ function abortError(signal) {
1524
+ return signal.reason ?? new DOMException("The operation was aborted", "AbortError");
1525
+ }
1526
+ async function delay(ms) {
1527
+ if (ms <= 0) {
1528
+ return;
1529
+ }
1530
+ await new Promise((resolve) => {
1531
+ setTimeout(resolve, ms);
1532
+ });
1533
+ }
1534
+ function isTimeoutAbort(reason) {
1535
+ return typeof reason === "object" && reason !== null && "code" in reason && reason.code === "timeout";
1536
+ }
1537
+
1262
1538
  // ../protocol/src/computer-use-bridge.ts
1263
1539
  var OPENSTEER_COMPUTER_USE_BRIDGE_SYMBOL = /* @__PURE__ */ Symbol.for("@opensteer/computer-use-bridge");
1264
1540
 
@@ -1743,6 +2019,7 @@ function createPlaywrightComputerUseBridge(context) {
1743
2019
  const startedAt = Date.now();
1744
2020
  const actionController = context.resolveController(input.pageRef);
1745
2021
  const action = input.action;
2022
+ let boundary;
1746
2023
  let actionMs = 0;
1747
2024
  let waitMs = 0;
1748
2025
  const actionStartedAt = Date.now();
@@ -1808,7 +2085,12 @@ function createPlaywrightComputerUseBridge(context) {
1808
2085
  await context.flushPendingPageTasks(actionController.sessionRef);
1809
2086
  if (action.type !== "screenshot" && action.type !== "wait") {
1810
2087
  const waitStartedAt = Date.now();
1811
- await input.policySettle(actionController.pageRef);
2088
+ boundary = await context.settleActionBoundary(actionController, {
2089
+ signal: input.signal,
2090
+ ...input.snapshot === void 0 ? {} : { snapshot: input.snapshot },
2091
+ remainingMs: input.remainingMs,
2092
+ policySettle: input.policySettle
2093
+ });
1812
2094
  waitMs = Date.now() - waitStartedAt;
1813
2095
  } else if (action.type === "wait") {
1814
2096
  waitMs = actionMs;
@@ -1820,7 +2102,11 @@ function createPlaywrightComputerUseBridge(context) {
1820
2102
  let resultController = context.resolveController(resultPageRef);
1821
2103
  if (action.type !== "screenshot" && action.type !== "wait" && resultController.pageRef !== actionController.pageRef) {
1822
2104
  const popupWaitStartedAt = Date.now();
1823
- await input.policySettle(resultController.pageRef);
2105
+ await context.settleActionBoundary(resultController, {
2106
+ signal: input.signal,
2107
+ remainingMs: input.remainingMs,
2108
+ policySettle: input.policySettle
2109
+ });
1824
2110
  waitMs += Date.now() - popupWaitStartedAt;
1825
2111
  await context.flushPendingPageTasks(actionController.sessionRef);
1826
2112
  resultController = context.resolveController(resultController.pageRef);
@@ -1844,7 +2130,8 @@ function createPlaywrightComputerUseBridge(context) {
1844
2130
  actionMs,
1845
2131
  waitMs,
1846
2132
  totalMs: Date.now() - startedAt
1847
- }
2133
+ },
2134
+ ...boundary === void 0 ? {} : { boundary }
1848
2135
  };
1849
2136
  }
1850
2137
  };
@@ -2877,10 +3164,12 @@ function createPlaywrightDomActionBridge(context) {
2877
3164
  },
2878
3165
  async finalizeDomAction(pageRef, options) {
2879
3166
  const controller = context.resolveController(pageRef);
2880
- await context.flushPendingPageTasks(controller.sessionRef);
2881
- await options.policySettle(pageRef);
2882
- await context.flushPendingPageTasks(controller.sessionRef);
2883
- await context.flushDomUpdateTask(controller);
3167
+ return context.settleActionBoundary(controller, {
3168
+ signal: options.signal,
3169
+ ...options.snapshot === void 0 ? {} : { snapshot: options.snapshot },
3170
+ remainingMs: options.remainingMs,
3171
+ policySettle: options.policySettle
3172
+ });
2884
3173
  }
2885
3174
  };
2886
3175
  }
@@ -3148,6 +3437,121 @@ async function releaseObject(controller, objectId) {
3148
3437
  await controller.cdp.send("Runtime.releaseObject", { objectId }).catch(() => void 0);
3149
3438
  }
3150
3439
 
3440
+ // src/action-settle.ts
3441
+ var DEFAULT_PLAYWRIGHT_ACTION_SETTLE_TIMEOUT_MS = CROSS_DOCUMENT_INTERACTION_TIMEOUT_MS;
3442
+ function clampPlaywrightActionSettleTimeout(timeoutMs) {
3443
+ if (timeoutMs === void 0) {
3444
+ return DEFAULT_PLAYWRIGHT_ACTION_SETTLE_TIMEOUT_MS;
3445
+ }
3446
+ return Math.max(0, Math.min(DEFAULT_PLAYWRIGHT_ACTION_SETTLE_TIMEOUT_MS, timeoutMs));
3447
+ }
3448
+ function createPlaywrightActionSettler(context) {
3449
+ const installScript = buildPostLoadTrackerInstallScript();
3450
+ const readExpression = buildPostLoadTrackerReadExpression();
3451
+ async function installTracker(controller) {
3452
+ if (!controller.settleTrackerRegistered) {
3453
+ await controller.page.addInitScript(installScript);
3454
+ controller.settleTrackerRegistered = true;
3455
+ }
3456
+ try {
3457
+ await controller.cdp.send("Runtime.evaluate", {
3458
+ expression: installScript,
3459
+ returnByValue: true,
3460
+ awaitPromise: true
3461
+ });
3462
+ } catch (error) {
3463
+ if (controller.lifecycleState === "closed" || isContextClosedError(error)) {
3464
+ return;
3465
+ }
3466
+ throw normalizePlaywrightError(error, controller.pageRef);
3467
+ }
3468
+ }
3469
+ async function readTrackerState(controller) {
3470
+ try {
3471
+ const evaluated = await controller.cdp.send("Runtime.evaluate", {
3472
+ expression: readExpression,
3473
+ returnByValue: true,
3474
+ awaitPromise: true
3475
+ });
3476
+ return normalizePostLoadTrackerState(evaluated.result?.value);
3477
+ } catch (error) {
3478
+ if (isIgnorableTrackerReadError(error)) {
3479
+ return void 0;
3480
+ }
3481
+ throw normalizePlaywrightError(error, controller.pageRef);
3482
+ }
3483
+ }
3484
+ async function settle(options) {
3485
+ const { controller, timeoutMs, signal, snapshot, policySettle } = options;
3486
+ if (timeoutMs <= 0) {
3487
+ return {
3488
+ trigger: "dom-action",
3489
+ crossDocument: false,
3490
+ bootstrapSettled: false,
3491
+ timedOutPhase: "bootstrap"
3492
+ };
3493
+ }
3494
+ await context.flushPendingPageTasks(controller.sessionRef);
3495
+ let boundary;
3496
+ if (snapshot === void 0) {
3497
+ if (policySettle) {
3498
+ if (signal?.aborted) {
3499
+ throw signal.reason ?? abortError2();
3500
+ }
3501
+ await policySettle(controller.pageRef, "dom-action");
3502
+ }
3503
+ boundary = {
3504
+ trigger: "dom-action",
3505
+ crossDocument: false,
3506
+ bootstrapSettled: true
3507
+ };
3508
+ } else {
3509
+ await installTracker(controller);
3510
+ boundary = await waitForActionBoundary({
3511
+ timeoutMs,
3512
+ ...signal === void 0 ? {} : { signal },
3513
+ snapshot,
3514
+ getCurrentMainFrameDocumentRef: () => context.getMainFrameDocumentRef(controller),
3515
+ waitForNavigationContentLoaded: async (remainingMs) => {
3516
+ try {
3517
+ await controller.page.waitForLoadState("domcontentloaded", {
3518
+ timeout: remainingMs
3519
+ });
3520
+ } catch (error) {
3521
+ if (controller.lifecycleState === "closed" || isContextClosedError(error)) {
3522
+ return;
3523
+ }
3524
+ throw normalizePlaywrightError(error, controller.pageRef);
3525
+ }
3526
+ },
3527
+ readTrackerState: () => readTrackerState(controller),
3528
+ throwBackgroundError: () => context.throwBackgroundError(controller),
3529
+ isPageClosed: () => controller.lifecycleState === "closed"
3530
+ });
3531
+ if (policySettle) {
3532
+ await policySettle(controller.pageRef, boundary.trigger);
3533
+ }
3534
+ }
3535
+ await context.flushPendingPageTasks(controller.sessionRef);
3536
+ if (controller.lifecycleState !== "closed") {
3537
+ await context.flushDomUpdateTask(controller);
3538
+ }
3539
+ return boundary;
3540
+ }
3541
+ return {
3542
+ installTracker,
3543
+ settle
3544
+ };
3545
+ }
3546
+ function abortError2() {
3547
+ return new DOMException("The operation was aborted", "AbortError");
3548
+ }
3549
+ function isIgnorableTrackerReadError(error) {
3550
+ return isContextClosedError(error) || error instanceof Error && /Execution context was destroyed|Cannot find context|Inspected target navigated or closed/i.test(
3551
+ error.message
3552
+ );
3553
+ }
3554
+
3151
3555
  // src/storage-capture.ts
3152
3556
  var ACTIVATION_PATH = "/__opensteer_storage_capture__";
3153
3557
  var ACTIVATION_TIMEOUT_MS = 15e3;
@@ -3354,6 +3758,12 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
3354
3758
  pageByPlaywrightPage = /* @__PURE__ */ new WeakMap();
3355
3759
  pendingPopupOpeners = /* @__PURE__ */ new WeakMap();
3356
3760
  preassignedPopupPageRefs = /* @__PURE__ */ new WeakMap();
3761
+ actionSettler = createPlaywrightActionSettler({
3762
+ flushPendingPageTasks: (sessionRef) => this.flushPendingPageTasks(sessionRef),
3763
+ flushDomUpdateTask: (controller) => this.flushDomUpdateTask(controller),
3764
+ getMainFrameDocumentRef: (controller) => controller.mainFrameRef === void 0 ? void 0 : this.frames.get(controller.mainFrameRef)?.currentDocument.documentRef,
3765
+ throwBackgroundError: (controller) => this.throwBackgroundError(controller)
3766
+ });
3357
3767
  pageCounter = 0;
3358
3768
  frameCounter = 0;
3359
3769
  documentCounter = 0;
@@ -3409,6 +3819,13 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
3409
3819
  resolveController: (pageRef) => this.requirePage(pageRef),
3410
3820
  flushPendingPageTasks: (sessionRef) => this.flushPendingPageTasks(sessionRef),
3411
3821
  flushDomUpdateTask: (controller) => this.flushDomUpdateTask(controller),
3822
+ settleActionBoundary: (controller, options) => this.actionSettler.settle({
3823
+ controller,
3824
+ timeoutMs: clampPlaywrightActionSettleTimeout(options.remainingMs()),
3825
+ ...options.signal === void 0 ? {} : { signal: options.signal },
3826
+ ...options.snapshot === void 0 ? {} : { snapshot: options.snapshot },
3827
+ ...options.policySettle === void 0 ? {} : { policySettle: options.policySettle }
3828
+ }),
3412
3829
  requireMainFrame: (controller) => this.requireMainFrame(controller),
3413
3830
  drainQueuedEvents: (pageRef) => this.drainQueuedEvents(pageRef),
3414
3831
  withModifiers: (page, modifiers, action) => this.withModifiers(page, modifiers, action)
@@ -3420,6 +3837,13 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
3420
3837
  resolveController: (pageRef) => this.requirePage(pageRef),
3421
3838
  flushPendingPageTasks: (sessionRef) => this.flushPendingPageTasks(sessionRef),
3422
3839
  flushDomUpdateTask: (controller) => this.flushDomUpdateTask(controller),
3840
+ settleActionBoundary: (controller, options) => this.actionSettler.settle({
3841
+ controller,
3842
+ timeoutMs: clampPlaywrightActionSettleTimeout(options.remainingMs()),
3843
+ ...options.signal === void 0 ? {} : { signal: options.signal },
3844
+ ...options.snapshot === void 0 ? {} : { snapshot: options.snapshot },
3845
+ ...options.policySettle === void 0 ? {} : { policySettle: options.policySettle }
3846
+ }),
3423
3847
  locateBackendNode: (document, backendNodeId) => createNodeLocator(
3424
3848
  document.documentRef,
3425
3849
  document.documentEpoch,
@@ -4514,6 +4938,7 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
4514
4938
  backgroundTasks: /* @__PURE__ */ new Set(),
4515
4939
  domUpdateTask: void 0,
4516
4940
  backgroundError: void 0,
4941
+ settleTrackerRegistered: false,
4517
4942
  openerPageRef: void 0,
4518
4943
  mainFrameRef: void 0,
4519
4944
  lifecycleState: "open",
@@ -4530,6 +4955,7 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
4530
4955
  await cdp.send("DOM.enable", { includeWhitespace: "none" });
4531
4956
  await cdp.send("DOMStorage.enable");
4532
4957
  await cdp.send("DOM.getDocument", { depth: 0 });
4958
+ await this.actionSettler.installTracker(controller);
4533
4959
  cdp.on(
4534
4960
  "Page.frameAttached",
4535
4961
  (payload) => this.runControllerEvent(