@opensteer/engine-playwright 0.8.2 → 0.8.4
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 +509 -81
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +52 -15
- package/dist/index.d.ts +52 -15
- package/dist/index.js +509 -81
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1277,19 +1277,24 @@ function normalizePostLoadTrackerState(value) {
|
|
|
1277
1277
|
const installedAt = readFiniteNumber(value.installedAt);
|
|
1278
1278
|
const lastMutationAt = readFiniteNumber(value.lastMutationAt);
|
|
1279
1279
|
const lastNetworkActivityAt = readFiniteNumber(value.lastNetworkActivityAt);
|
|
1280
|
+
const lastTrackedNetworkActivityAt = readFiniteNumber(value.lastTrackedNetworkActivityAt);
|
|
1280
1281
|
const now = readFiniteNumber(value.now);
|
|
1281
1282
|
const readyState = typeof value.readyState === "string" ? value.readyState : void 0;
|
|
1282
|
-
if (installedAt === void 0 || lastMutationAt === void 0 || lastNetworkActivityAt === void 0 || now === void 0 || readyState === void 0) {
|
|
1283
|
+
if (installedAt === void 0 || lastMutationAt === void 0 || lastNetworkActivityAt === void 0 || lastTrackedNetworkActivityAt === void 0 || now === void 0 || readyState === void 0) {
|
|
1283
1284
|
return void 0;
|
|
1284
1285
|
}
|
|
1285
1286
|
return {
|
|
1286
1287
|
installedAt,
|
|
1287
1288
|
lastMutationAt,
|
|
1288
1289
|
lastNetworkActivityAt,
|
|
1290
|
+
lastTrackedNetworkActivityAt,
|
|
1289
1291
|
now,
|
|
1290
1292
|
pendingFetches: readNonNegativeNumber(value.pendingFetches),
|
|
1291
1293
|
pendingTimeouts: readNonNegativeNumber(value.pendingTimeouts),
|
|
1292
1294
|
pendingXhrs: readNonNegativeNumber(value.pendingXhrs),
|
|
1295
|
+
trackedPendingFetches: readNonNegativeNumber(value.trackedPendingFetches),
|
|
1296
|
+
trackedPendingXhrs: readNonNegativeNumber(value.trackedPendingXhrs),
|
|
1297
|
+
collecting: value.collecting === true,
|
|
1293
1298
|
readyState
|
|
1294
1299
|
};
|
|
1295
1300
|
}
|
|
@@ -1304,11 +1309,14 @@ function buildPostLoadTrackerInstallScript() {
|
|
|
1304
1309
|
installedAt: performance.now(),
|
|
1305
1310
|
lastMutationAt: performance.now(),
|
|
1306
1311
|
lastNetworkActivityAt: performance.now(),
|
|
1312
|
+
lastTrackedNetworkActivityAt: performance.now(),
|
|
1307
1313
|
pendingFetches: 0,
|
|
1308
1314
|
pendingTimeouts: 0,
|
|
1309
1315
|
pendingXhrs: 0,
|
|
1316
|
+
trackedPendingFetches: 0,
|
|
1317
|
+
trackedPendingXhrs: 0,
|
|
1318
|
+
collecting: true,
|
|
1310
1319
|
readyState: document.readyState,
|
|
1311
|
-
timeoutIds: new Set(),
|
|
1312
1320
|
};
|
|
1313
1321
|
globalObject.__opensteerActionBoundaryTrackerInstalled = true;
|
|
1314
1322
|
globalObject.__opensteerActionBoundaryTracker = tracker;
|
|
@@ -1321,6 +1329,18 @@ function buildPostLoadTrackerInstallScript() {
|
|
|
1321
1329
|
tracker.lastNetworkActivityAt = performance.now();
|
|
1322
1330
|
tracker.readyState = document.readyState;
|
|
1323
1331
|
};
|
|
1332
|
+
const markTrackedNetwork = () => {
|
|
1333
|
+
tracker.lastTrackedNetworkActivityAt = performance.now();
|
|
1334
|
+
markNetwork();
|
|
1335
|
+
};
|
|
1336
|
+
const resetTracking = () => {
|
|
1337
|
+
const now = performance.now();
|
|
1338
|
+
tracker.lastTrackedNetworkActivityAt = now;
|
|
1339
|
+
tracker.trackedPendingFetches = 0;
|
|
1340
|
+
tracker.trackedPendingXhrs = 0;
|
|
1341
|
+
tracker.collecting = true;
|
|
1342
|
+
tracker.readyState = document.readyState;
|
|
1343
|
+
};
|
|
1324
1344
|
|
|
1325
1345
|
const startObserver = () => {
|
|
1326
1346
|
const target = document.documentElement ?? document;
|
|
@@ -1346,45 +1366,26 @@ function buildPostLoadTrackerInstallScript() {
|
|
|
1346
1366
|
document.addEventListener("readystatechange", markMutation);
|
|
1347
1367
|
addEventListener("load", markMutation, { once: true });
|
|
1348
1368
|
|
|
1349
|
-
const nativeSetTimeout = globalObject.setTimeout.bind(globalObject);
|
|
1350
|
-
const nativeClearTimeout = globalObject.clearTimeout.bind(globalObject);
|
|
1351
|
-
globalObject.setTimeout = function(callback, delay, ...args) {
|
|
1352
|
-
tracker.pendingTimeouts += 1;
|
|
1353
|
-
markNetwork();
|
|
1354
|
-
let handle;
|
|
1355
|
-
const wrapped =
|
|
1356
|
-
typeof callback === "function"
|
|
1357
|
-
? (...callbackArgs) => {
|
|
1358
|
-
if (tracker.timeoutIds.delete(handle)) {
|
|
1359
|
-
tracker.pendingTimeouts = Math.max(0, tracker.pendingTimeouts - 1);
|
|
1360
|
-
}
|
|
1361
|
-
try {
|
|
1362
|
-
return callback(...callbackArgs);
|
|
1363
|
-
} finally {
|
|
1364
|
-
markMutation();
|
|
1365
|
-
}
|
|
1366
|
-
}
|
|
1367
|
-
: callback;
|
|
1368
|
-
handle = nativeSetTimeout(wrapped, delay, ...args);
|
|
1369
|
-
tracker.timeoutIds.add(handle);
|
|
1370
|
-
return handle;
|
|
1371
|
-
};
|
|
1372
|
-
globalObject.clearTimeout = function(handle) {
|
|
1373
|
-
if (tracker.timeoutIds.delete(handle)) {
|
|
1374
|
-
tracker.pendingTimeouts = Math.max(0, tracker.pendingTimeouts - 1);
|
|
1375
|
-
}
|
|
1376
|
-
return nativeClearTimeout(handle);
|
|
1377
|
-
};
|
|
1378
|
-
|
|
1379
1369
|
if (typeof globalObject.fetch === "function") {
|
|
1380
1370
|
const nativeFetch = globalObject.fetch.bind(globalObject);
|
|
1381
1371
|
globalObject.fetch = (...args) => {
|
|
1372
|
+
const tracked = tracker.collecting === true;
|
|
1382
1373
|
tracker.pendingFetches += 1;
|
|
1383
|
-
|
|
1374
|
+
if (tracked) {
|
|
1375
|
+
tracker.trackedPendingFetches += 1;
|
|
1376
|
+
markTrackedNetwork();
|
|
1377
|
+
} else {
|
|
1378
|
+
markNetwork();
|
|
1379
|
+
}
|
|
1384
1380
|
return nativeFetch(...args)
|
|
1385
1381
|
.finally(() => {
|
|
1386
1382
|
tracker.pendingFetches = Math.max(0, tracker.pendingFetches - 1);
|
|
1387
|
-
|
|
1383
|
+
if (tracked) {
|
|
1384
|
+
tracker.trackedPendingFetches = Math.max(0, tracker.trackedPendingFetches - 1);
|
|
1385
|
+
markTrackedNetwork();
|
|
1386
|
+
} else {
|
|
1387
|
+
markNetwork();
|
|
1388
|
+
}
|
|
1388
1389
|
});
|
|
1389
1390
|
};
|
|
1390
1391
|
}
|
|
@@ -1393,21 +1394,60 @@ function buildPostLoadTrackerInstallScript() {
|
|
|
1393
1394
|
const NativeXMLHttpRequest = globalObject.XMLHttpRequest;
|
|
1394
1395
|
const nativeSend = NativeXMLHttpRequest.prototype.send;
|
|
1395
1396
|
NativeXMLHttpRequest.prototype.send = function(...args) {
|
|
1397
|
+
const tracked = tracker.collecting === true;
|
|
1396
1398
|
tracker.pendingXhrs += 1;
|
|
1397
|
-
|
|
1399
|
+
if (tracked) {
|
|
1400
|
+
tracker.trackedPendingXhrs += 1;
|
|
1401
|
+
markTrackedNetwork();
|
|
1402
|
+
} else {
|
|
1403
|
+
markNetwork();
|
|
1404
|
+
}
|
|
1398
1405
|
const finalize = () => {
|
|
1399
1406
|
this.removeEventListener("loadend", finalize);
|
|
1400
1407
|
tracker.pendingXhrs = Math.max(0, tracker.pendingXhrs - 1);
|
|
1401
|
-
|
|
1408
|
+
if (tracked) {
|
|
1409
|
+
tracker.trackedPendingXhrs = Math.max(0, tracker.trackedPendingXhrs - 1);
|
|
1410
|
+
markTrackedNetwork();
|
|
1411
|
+
} else {
|
|
1412
|
+
markNetwork();
|
|
1413
|
+
}
|
|
1402
1414
|
};
|
|
1403
1415
|
this.addEventListener("loadend", finalize, { once: true });
|
|
1404
1416
|
return nativeSend.apply(this, args);
|
|
1405
1417
|
};
|
|
1406
1418
|
}
|
|
1407
1419
|
|
|
1420
|
+
tracker.beginObservation = () => {
|
|
1421
|
+
resetTracking();
|
|
1422
|
+
return true;
|
|
1423
|
+
};
|
|
1424
|
+
tracker.freezeObservation = () => {
|
|
1425
|
+
tracker.collecting = false;
|
|
1426
|
+
tracker.readyState = document.readyState;
|
|
1427
|
+
return true;
|
|
1428
|
+
};
|
|
1429
|
+
|
|
1408
1430
|
return true;
|
|
1409
1431
|
})()`;
|
|
1410
1432
|
}
|
|
1433
|
+
function buildPostLoadTrackerBeginExpression() {
|
|
1434
|
+
return `(() => {
|
|
1435
|
+
const tracker = globalThis.__opensteerActionBoundaryTracker;
|
|
1436
|
+
if (!tracker || typeof tracker.beginObservation !== "function") {
|
|
1437
|
+
return false;
|
|
1438
|
+
}
|
|
1439
|
+
return tracker.beginObservation();
|
|
1440
|
+
})()`;
|
|
1441
|
+
}
|
|
1442
|
+
function buildPostLoadTrackerFreezeExpression() {
|
|
1443
|
+
return `(() => {
|
|
1444
|
+
const tracker = globalThis.__opensteerActionBoundaryTracker;
|
|
1445
|
+
if (!tracker || typeof tracker.freezeObservation !== "function") {
|
|
1446
|
+
return false;
|
|
1447
|
+
}
|
|
1448
|
+
return tracker.freezeObservation();
|
|
1449
|
+
})()`;
|
|
1450
|
+
}
|
|
1411
1451
|
function buildPostLoadTrackerReadExpression() {
|
|
1412
1452
|
return `(() => {
|
|
1413
1453
|
const tracker = globalThis.__opensteerActionBoundaryTracker;
|
|
@@ -1419,14 +1459,31 @@ function buildPostLoadTrackerReadExpression() {
|
|
|
1419
1459
|
installedAt: Number(tracker.installedAt ?? 0),
|
|
1420
1460
|
lastMutationAt: Number(tracker.lastMutationAt ?? 0),
|
|
1421
1461
|
lastNetworkActivityAt: Number(tracker.lastNetworkActivityAt ?? 0),
|
|
1462
|
+
lastTrackedNetworkActivityAt: Number(tracker.lastTrackedNetworkActivityAt ?? 0),
|
|
1422
1463
|
now: Number(performance.now()),
|
|
1423
1464
|
pendingFetches: Number(tracker.pendingFetches ?? 0),
|
|
1424
1465
|
pendingTimeouts: Number(tracker.pendingTimeouts ?? 0),
|
|
1425
1466
|
pendingXhrs: Number(tracker.pendingXhrs ?? 0),
|
|
1467
|
+
trackedPendingFetches: Number(tracker.trackedPendingFetches ?? 0),
|
|
1468
|
+
trackedPendingXhrs: Number(tracker.trackedPendingXhrs ?? 0),
|
|
1469
|
+
collecting: tracker.collecting === true,
|
|
1426
1470
|
readyState: String(document.readyState),
|
|
1427
1471
|
};
|
|
1428
1472
|
})()`;
|
|
1429
1473
|
}
|
|
1474
|
+
function capturePostLoadTrackerSnapshot(tracker) {
|
|
1475
|
+
return {
|
|
1476
|
+
lastTrackedNetworkActivityAt: tracker.lastTrackedNetworkActivityAt,
|
|
1477
|
+
trackedPendingFetches: tracker.trackedPendingFetches,
|
|
1478
|
+
trackedPendingXhrs: tracker.trackedPendingXhrs
|
|
1479
|
+
};
|
|
1480
|
+
}
|
|
1481
|
+
function postLoadTrackerHasTrackedNetworkActivitySince(snapshot, tracker) {
|
|
1482
|
+
if (!tracker) {
|
|
1483
|
+
return false;
|
|
1484
|
+
}
|
|
1485
|
+
return tracker.trackedPendingFetches > snapshot.trackedPendingFetches || tracker.trackedPendingXhrs > snapshot.trackedPendingXhrs || tracker.lastTrackedNetworkActivityAt > snapshot.lastTrackedNetworkActivityAt;
|
|
1486
|
+
}
|
|
1430
1487
|
function postLoadTrackerIsSettled(tracker, quietWindowMs = DEFAULT_POST_LOAD_TRACKER_QUIET_WINDOW_MS) {
|
|
1431
1488
|
if (!tracker) {
|
|
1432
1489
|
return false;
|
|
@@ -1434,13 +1491,13 @@ function postLoadTrackerIsSettled(tracker, quietWindowMs = DEFAULT_POST_LOAD_TRA
|
|
|
1434
1491
|
if (tracker.readyState !== "complete") {
|
|
1435
1492
|
return false;
|
|
1436
1493
|
}
|
|
1437
|
-
if (tracker.
|
|
1494
|
+
if (tracker.trackedPendingFetches > 0 || tracker.trackedPendingXhrs > 0) {
|
|
1438
1495
|
return false;
|
|
1439
1496
|
}
|
|
1440
1497
|
const lastActivityAt = Math.max(
|
|
1441
1498
|
tracker.installedAt,
|
|
1442
1499
|
tracker.lastMutationAt,
|
|
1443
|
-
tracker.
|
|
1500
|
+
tracker.lastTrackedNetworkActivityAt
|
|
1444
1501
|
);
|
|
1445
1502
|
return tracker.now - lastActivityAt >= quietWindowMs;
|
|
1446
1503
|
}
|
|
@@ -1462,7 +1519,7 @@ async function waitForActionBoundary(input) {
|
|
|
1462
1519
|
const pollIntervalMs = input.pollIntervalMs ?? DEFAULT_ACTION_BOUNDARY_POLL_INTERVAL_MS;
|
|
1463
1520
|
let trigger = "dom-action";
|
|
1464
1521
|
let crossDocument = false;
|
|
1465
|
-
let
|
|
1522
|
+
let sameDocumentAsyncActivity = false;
|
|
1466
1523
|
while (Date.now() < deadline) {
|
|
1467
1524
|
input.throwBackgroundError();
|
|
1468
1525
|
if (input.isPageClosed()) {
|
|
@@ -1484,16 +1541,21 @@ async function waitForActionBoundary(input) {
|
|
|
1484
1541
|
throw abortError(input.signal);
|
|
1485
1542
|
}
|
|
1486
1543
|
const currentDocumentRef = input.getCurrentMainFrameDocumentRef();
|
|
1544
|
+
const currentPageUrl = input.getCurrentPageUrl?.();
|
|
1487
1545
|
if (input.snapshot !== void 0 && currentDocumentRef !== void 0 && currentDocumentRef !== input.snapshot.documentRef) {
|
|
1488
1546
|
trigger = "navigation";
|
|
1489
1547
|
crossDocument = true;
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1548
|
+
}
|
|
1549
|
+
if (!crossDocument && !sameDocumentAsyncActivity && input.snapshot?.tracker !== void 0 && postLoadTrackerHasTrackedNetworkActivitySince(
|
|
1550
|
+
input.snapshot.tracker,
|
|
1551
|
+
await input.readTrackerState()
|
|
1552
|
+
)) {
|
|
1553
|
+
trigger = "navigation";
|
|
1554
|
+
sameDocumentAsyncActivity = true;
|
|
1555
|
+
}
|
|
1556
|
+
if (!crossDocument && input.snapshot?.url !== void 0 && currentPageUrl !== void 0 && currentPageUrl !== input.snapshot.url && input.isCurrentMainFrameBootstrapSettled !== void 0 && !input.isCurrentMainFrameBootstrapSettled()) {
|
|
1557
|
+
trigger = "navigation";
|
|
1558
|
+
crossDocument = true;
|
|
1497
1559
|
}
|
|
1498
1560
|
if (!crossDocument && crossDocumentDetectionDeadline !== void 0 && Date.now() >= crossDocumentDetectionDeadline) {
|
|
1499
1561
|
return {
|
|
@@ -1502,7 +1564,18 @@ async function waitForActionBoundary(input) {
|
|
|
1502
1564
|
bootstrapSettled: true
|
|
1503
1565
|
};
|
|
1504
1566
|
}
|
|
1505
|
-
if (
|
|
1567
|
+
if (sameDocumentAsyncActivity) {
|
|
1568
|
+
return {
|
|
1569
|
+
trigger,
|
|
1570
|
+
crossDocument,
|
|
1571
|
+
bootstrapSettled: true
|
|
1572
|
+
};
|
|
1573
|
+
}
|
|
1574
|
+
if (crossDocument && input.isCurrentMainFrameBootstrapSettled !== void 0 && !input.isCurrentMainFrameBootstrapSettled()) {
|
|
1575
|
+
await delay(Math.min(pollIntervalMs, Math.max(0, deadline - Date.now())));
|
|
1576
|
+
continue;
|
|
1577
|
+
}
|
|
1578
|
+
if (crossDocument) {
|
|
1506
1579
|
return {
|
|
1507
1580
|
trigger,
|
|
1508
1581
|
crossDocument,
|
|
@@ -3437,6 +3510,7 @@ async function releaseObject(controller, objectId) {
|
|
|
3437
3510
|
|
|
3438
3511
|
// src/action-settle.ts
|
|
3439
3512
|
var DEFAULT_PLAYWRIGHT_ACTION_SETTLE_TIMEOUT_MS = CROSS_DOCUMENT_INTERACTION_TIMEOUT_MS;
|
|
3513
|
+
var DEFAULT_PLAYWRIGHT_POST_LOAD_CAPTURE_WINDOW_MS = 1e3;
|
|
3440
3514
|
function clampPlaywrightActionSettleTimeout(timeoutMs) {
|
|
3441
3515
|
if (timeoutMs === void 0) {
|
|
3442
3516
|
return DEFAULT_PLAYWRIGHT_ACTION_SETTLE_TIMEOUT_MS;
|
|
@@ -3445,6 +3519,8 @@ function clampPlaywrightActionSettleTimeout(timeoutMs) {
|
|
|
3445
3519
|
}
|
|
3446
3520
|
function createPlaywrightActionSettler(context) {
|
|
3447
3521
|
const installScript = buildPostLoadTrackerInstallScript();
|
|
3522
|
+
const beginExpression = buildPostLoadTrackerBeginExpression();
|
|
3523
|
+
const freezeExpression = buildPostLoadTrackerFreezeExpression();
|
|
3448
3524
|
const readExpression = buildPostLoadTrackerReadExpression();
|
|
3449
3525
|
async function installTracker(controller) {
|
|
3450
3526
|
if (!controller.settleTrackerRegistered) {
|
|
@@ -3479,6 +3555,79 @@ function createPlaywrightActionSettler(context) {
|
|
|
3479
3555
|
throw normalizePlaywrightError(error, controller.pageRef);
|
|
3480
3556
|
}
|
|
3481
3557
|
}
|
|
3558
|
+
async function beginTrackerObservation(controller) {
|
|
3559
|
+
await installTracker(controller);
|
|
3560
|
+
try {
|
|
3561
|
+
await controller.cdp.send("Runtime.evaluate", {
|
|
3562
|
+
expression: beginExpression,
|
|
3563
|
+
returnByValue: true,
|
|
3564
|
+
awaitPromise: true
|
|
3565
|
+
});
|
|
3566
|
+
} catch (error) {
|
|
3567
|
+
if (isIgnorableTrackerReadError(error)) {
|
|
3568
|
+
return;
|
|
3569
|
+
}
|
|
3570
|
+
throw normalizePlaywrightError(error, controller.pageRef);
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3573
|
+
async function freezeTrackerObservation(controller) {
|
|
3574
|
+
try {
|
|
3575
|
+
await controller.cdp.send("Runtime.evaluate", {
|
|
3576
|
+
expression: freezeExpression,
|
|
3577
|
+
returnByValue: true,
|
|
3578
|
+
awaitPromise: true
|
|
3579
|
+
});
|
|
3580
|
+
} catch (error) {
|
|
3581
|
+
if (isIgnorableTrackerReadError(error)) {
|
|
3582
|
+
return;
|
|
3583
|
+
}
|
|
3584
|
+
throw normalizePlaywrightError(error, controller.pageRef);
|
|
3585
|
+
}
|
|
3586
|
+
}
|
|
3587
|
+
async function captureSnapshot(controller) {
|
|
3588
|
+
const documentRef = context.getMainFrameDocumentRef(controller);
|
|
3589
|
+
if (documentRef === void 0) {
|
|
3590
|
+
throw new Error(`page ${controller.pageRef} does not expose a main frame`);
|
|
3591
|
+
}
|
|
3592
|
+
await beginTrackerObservation(controller);
|
|
3593
|
+
const tracker = await readTrackerState(controller);
|
|
3594
|
+
return {
|
|
3595
|
+
pageRef: controller.pageRef,
|
|
3596
|
+
documentRef,
|
|
3597
|
+
url: controller.page.url(),
|
|
3598
|
+
...tracker === void 0 ? {} : { tracker: capturePostLoadTrackerSnapshot(tracker) }
|
|
3599
|
+
};
|
|
3600
|
+
}
|
|
3601
|
+
async function waitForPostLoadQuiet(input) {
|
|
3602
|
+
const { controller, timeoutMs, signal } = input;
|
|
3603
|
+
if (timeoutMs <= 0) {
|
|
3604
|
+
return;
|
|
3605
|
+
}
|
|
3606
|
+
const quietMs = input.quietMs ?? DEFAULT_POST_LOAD_TRACKER_QUIET_WINDOW_MS;
|
|
3607
|
+
const captureWindowMs = Math.max(
|
|
3608
|
+
0,
|
|
3609
|
+
Math.min(input.captureWindowMs ?? DEFAULT_PLAYWRIGHT_POST_LOAD_CAPTURE_WINDOW_MS, timeoutMs)
|
|
3610
|
+
);
|
|
3611
|
+
const deadline = Date.now() + timeoutMs;
|
|
3612
|
+
await installTracker(controller);
|
|
3613
|
+
if (captureWindowMs > 0) {
|
|
3614
|
+
await delayWithSignal2(captureWindowMs, signal, deadline);
|
|
3615
|
+
}
|
|
3616
|
+
await freezeTrackerObservation(controller);
|
|
3617
|
+
while (Date.now() < deadline) {
|
|
3618
|
+
if (signal?.aborted) {
|
|
3619
|
+
throw signal.reason ?? abortError2();
|
|
3620
|
+
}
|
|
3621
|
+
context.throwBackgroundError(controller);
|
|
3622
|
+
if (controller.lifecycleState === "closed") {
|
|
3623
|
+
return;
|
|
3624
|
+
}
|
|
3625
|
+
if (postLoadTrackerIsSettled(await readTrackerState(controller), quietMs)) {
|
|
3626
|
+
return;
|
|
3627
|
+
}
|
|
3628
|
+
await delayWithSignal2(100, signal, deadline);
|
|
3629
|
+
}
|
|
3630
|
+
}
|
|
3482
3631
|
async function settle(options) {
|
|
3483
3632
|
const { controller, timeoutMs, signal, snapshot, policySettle } = options;
|
|
3484
3633
|
if (timeoutMs <= 0) {
|
|
@@ -3510,18 +3659,8 @@ function createPlaywrightActionSettler(context) {
|
|
|
3510
3659
|
...signal === void 0 ? {} : { signal },
|
|
3511
3660
|
snapshot,
|
|
3512
3661
|
getCurrentMainFrameDocumentRef: () => context.getMainFrameDocumentRef(controller),
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
await controller.page.waitForLoadState("domcontentloaded", {
|
|
3516
|
-
timeout: remainingMs
|
|
3517
|
-
});
|
|
3518
|
-
} catch (error) {
|
|
3519
|
-
if (controller.lifecycleState === "closed" || isContextClosedError(error)) {
|
|
3520
|
-
return;
|
|
3521
|
-
}
|
|
3522
|
-
throw normalizePlaywrightError(error, controller.pageRef);
|
|
3523
|
-
}
|
|
3524
|
-
},
|
|
3662
|
+
getCurrentPageUrl: () => controller.page.url(),
|
|
3663
|
+
isCurrentMainFrameBootstrapSettled: () => context.isCurrentMainFrameBootstrapSettled(controller),
|
|
3525
3664
|
readTrackerState: () => readTrackerState(controller),
|
|
3526
3665
|
throwBackgroundError: () => context.throwBackgroundError(controller),
|
|
3527
3666
|
isPageClosed: () => controller.lifecycleState === "closed"
|
|
@@ -3537,13 +3676,36 @@ function createPlaywrightActionSettler(context) {
|
|
|
3537
3676
|
return boundary;
|
|
3538
3677
|
}
|
|
3539
3678
|
return {
|
|
3679
|
+
captureSnapshot,
|
|
3540
3680
|
installTracker,
|
|
3681
|
+
waitForPostLoadQuiet,
|
|
3541
3682
|
settle
|
|
3542
3683
|
};
|
|
3543
3684
|
}
|
|
3544
3685
|
function abortError2() {
|
|
3545
3686
|
return new DOMException("The operation was aborted", "AbortError");
|
|
3546
3687
|
}
|
|
3688
|
+
async function delayWithSignal2(delayMs, signal, deadline) {
|
|
3689
|
+
const effectiveDelay = Math.max(0, Math.min(delayMs, Math.max(0, deadline - Date.now())));
|
|
3690
|
+
if (effectiveDelay <= 0) {
|
|
3691
|
+
return;
|
|
3692
|
+
}
|
|
3693
|
+
if (signal?.aborted) {
|
|
3694
|
+
throw signal.reason ?? abortError2();
|
|
3695
|
+
}
|
|
3696
|
+
await new Promise((resolve, reject) => {
|
|
3697
|
+
const timer = setTimeout(() => {
|
|
3698
|
+
signal?.removeEventListener("abort", onAbort);
|
|
3699
|
+
resolve();
|
|
3700
|
+
}, effectiveDelay);
|
|
3701
|
+
const onAbort = () => {
|
|
3702
|
+
clearTimeout(timer);
|
|
3703
|
+
signal?.removeEventListener("abort", onAbort);
|
|
3704
|
+
reject(signal?.reason ?? abortError2());
|
|
3705
|
+
};
|
|
3706
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
3707
|
+
});
|
|
3708
|
+
}
|
|
3547
3709
|
function isIgnorableTrackerReadError(error) {
|
|
3548
3710
|
return isContextClosedError(error) || error instanceof Error && /Execution context was destroyed|Cannot find context|Inspected target navigated or closed/i.test(
|
|
3549
3711
|
error.message
|
|
@@ -3741,6 +3903,71 @@ function cloneKeyPath(keyPath) {
|
|
|
3741
3903
|
}
|
|
3742
3904
|
|
|
3743
3905
|
// src/engine.ts
|
|
3906
|
+
var PLAYWRIGHT_RUNTIME_EVENT_RECORDER_SOURCE = String.raw`(() => {
|
|
3907
|
+
const key = "__opensteerRuntimeEventRecorder";
|
|
3908
|
+
const globalScope = globalThis;
|
|
3909
|
+
if (globalScope[key]?.installed === true) {
|
|
3910
|
+
return;
|
|
3911
|
+
}
|
|
3912
|
+
|
|
3913
|
+
const queue = [];
|
|
3914
|
+
const limit = 500;
|
|
3915
|
+
const asString = (value) => {
|
|
3916
|
+
if (typeof value === "string") {
|
|
3917
|
+
return value;
|
|
3918
|
+
}
|
|
3919
|
+
if (typeof value === "number" || typeof value === "boolean" || value === null) {
|
|
3920
|
+
return String(value);
|
|
3921
|
+
}
|
|
3922
|
+
if (value === undefined) {
|
|
3923
|
+
return "undefined";
|
|
3924
|
+
}
|
|
3925
|
+
try {
|
|
3926
|
+
return JSON.stringify(value);
|
|
3927
|
+
} catch {
|
|
3928
|
+
return String(value);
|
|
3929
|
+
}
|
|
3930
|
+
};
|
|
3931
|
+
const enqueue = (entry) => {
|
|
3932
|
+
queue.push({
|
|
3933
|
+
...entry,
|
|
3934
|
+
timestamp: Date.now(),
|
|
3935
|
+
});
|
|
3936
|
+
if (queue.length > limit) {
|
|
3937
|
+
queue.splice(0, queue.length - limit);
|
|
3938
|
+
}
|
|
3939
|
+
};
|
|
3940
|
+
|
|
3941
|
+
globalScope.addEventListener("error", (event) => {
|
|
3942
|
+
enqueue({
|
|
3943
|
+
kind: "page-error",
|
|
3944
|
+
message:
|
|
3945
|
+
typeof event.message === "string" && event.message.length > 0
|
|
3946
|
+
? event.message
|
|
3947
|
+
: event.error?.message || "Uncaught exception",
|
|
3948
|
+
stack: typeof event.error?.stack === "string" ? event.error.stack : undefined,
|
|
3949
|
+
});
|
|
3950
|
+
});
|
|
3951
|
+
|
|
3952
|
+
globalScope.addEventListener("unhandledrejection", (event) => {
|
|
3953
|
+
const reason = event.reason;
|
|
3954
|
+
enqueue({
|
|
3955
|
+
kind: "page-error",
|
|
3956
|
+
message:
|
|
3957
|
+
typeof reason?.message === "string" && reason.message.length > 0
|
|
3958
|
+
? reason.message
|
|
3959
|
+
: asString(reason),
|
|
3960
|
+
stack: typeof reason?.stack === "string" ? reason.stack : undefined,
|
|
3961
|
+
});
|
|
3962
|
+
});
|
|
3963
|
+
|
|
3964
|
+
globalScope[key] = {
|
|
3965
|
+
installed: true,
|
|
3966
|
+
drain() {
|
|
3967
|
+
return queue.splice(0, queue.length);
|
|
3968
|
+
},
|
|
3969
|
+
};
|
|
3970
|
+
})();`;
|
|
3744
3971
|
var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
3745
3972
|
capabilities = PLAYWRIGHT_BROWSER_CORE_CAPABILITIES;
|
|
3746
3973
|
browser;
|
|
@@ -3760,6 +3987,7 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
3760
3987
|
flushPendingPageTasks: (sessionRef) => this.flushPendingPageTasks(sessionRef),
|
|
3761
3988
|
flushDomUpdateTask: (controller) => this.flushDomUpdateTask(controller),
|
|
3762
3989
|
getMainFrameDocumentRef: (controller) => controller.mainFrameRef === void 0 ? void 0 : this.frames.get(controller.mainFrameRef)?.currentDocument.documentRef,
|
|
3990
|
+
isCurrentMainFrameBootstrapSettled: (controller) => controller.mainFrameRef !== void 0 && this.frames.get(controller.mainFrameRef)?.currentDocument.domContentLoadedAt !== void 0,
|
|
3763
3991
|
throwBackgroundError: (controller) => this.throwBackgroundError(controller)
|
|
3764
3992
|
});
|
|
3765
3993
|
pageCounter = 0;
|
|
@@ -4172,11 +4400,15 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
4172
4400
|
});
|
|
4173
4401
|
await this.flushPendingPageTasks(controller.sessionRef);
|
|
4174
4402
|
const mainFrame = this.requireMainFrame(controller);
|
|
4403
|
+
const events = mergeDistinctStepEvents([
|
|
4404
|
+
...this.drainQueuedEvents(controller.pageRef),
|
|
4405
|
+
...await this.drainInstrumentedRuntimeEvents(controller)
|
|
4406
|
+
]);
|
|
4175
4407
|
return this.createStepResult(controller.sessionRef, controller.pageRef, startedAt, {
|
|
4176
4408
|
frameRef: mainFrame.frameRef,
|
|
4177
4409
|
documentRef: mainFrame.currentDocument.documentRef,
|
|
4178
4410
|
documentEpoch: mainFrame.currentDocument.documentEpoch,
|
|
4179
|
-
events
|
|
4411
|
+
events,
|
|
4180
4412
|
data: hit
|
|
4181
4413
|
});
|
|
4182
4414
|
}
|
|
@@ -4196,11 +4428,15 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
4196
4428
|
await this.flushPendingPageTasks(controller.sessionRef);
|
|
4197
4429
|
await this.flushDomUpdateTask(controller);
|
|
4198
4430
|
const mainFrame = this.requireMainFrame(controller);
|
|
4431
|
+
const events = mergeDistinctStepEvents([
|
|
4432
|
+
...this.drainQueuedEvents(controller.pageRef),
|
|
4433
|
+
...await this.drainInstrumentedRuntimeEvents(controller)
|
|
4434
|
+
]);
|
|
4199
4435
|
return this.createStepResult(controller.sessionRef, controller.pageRef, startedAt, {
|
|
4200
4436
|
frameRef: mainFrame.frameRef,
|
|
4201
4437
|
documentRef: mainFrame.currentDocument.documentRef,
|
|
4202
4438
|
documentEpoch: mainFrame.currentDocument.documentEpoch,
|
|
4203
|
-
events
|
|
4439
|
+
events,
|
|
4204
4440
|
data: void 0
|
|
4205
4441
|
});
|
|
4206
4442
|
}
|
|
@@ -4212,11 +4448,15 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
4212
4448
|
});
|
|
4213
4449
|
await this.flushPendingPageTasks(controller.sessionRef);
|
|
4214
4450
|
const mainFrame = this.requireMainFrame(controller);
|
|
4451
|
+
const events = mergeDistinctStepEvents([
|
|
4452
|
+
...this.drainQueuedEvents(controller.pageRef),
|
|
4453
|
+
...await this.drainInstrumentedRuntimeEvents(controller)
|
|
4454
|
+
]);
|
|
4215
4455
|
return this.createStepResult(controller.sessionRef, controller.pageRef, startedAt, {
|
|
4216
4456
|
frameRef: mainFrame.frameRef,
|
|
4217
4457
|
documentRef: mainFrame.currentDocument.documentRef,
|
|
4218
4458
|
documentEpoch: mainFrame.currentDocument.documentEpoch,
|
|
4219
|
-
events
|
|
4459
|
+
events,
|
|
4220
4460
|
data: void 0
|
|
4221
4461
|
});
|
|
4222
4462
|
}
|
|
@@ -4226,11 +4466,15 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
4226
4466
|
await controller.page.keyboard.type(input.text);
|
|
4227
4467
|
await this.flushPendingPageTasks(controller.sessionRef);
|
|
4228
4468
|
const mainFrame = this.requireMainFrame(controller);
|
|
4469
|
+
const events = mergeDistinctStepEvents([
|
|
4470
|
+
...this.drainQueuedEvents(controller.pageRef),
|
|
4471
|
+
...await this.drainInstrumentedRuntimeEvents(controller)
|
|
4472
|
+
]);
|
|
4229
4473
|
return this.createStepResult(controller.sessionRef, controller.pageRef, startedAt, {
|
|
4230
4474
|
frameRef: mainFrame.frameRef,
|
|
4231
4475
|
documentRef: mainFrame.currentDocument.documentRef,
|
|
4232
4476
|
documentEpoch: mainFrame.currentDocument.documentEpoch,
|
|
4233
|
-
events
|
|
4477
|
+
events,
|
|
4234
4478
|
data: void 0
|
|
4235
4479
|
});
|
|
4236
4480
|
}
|
|
@@ -4368,6 +4612,13 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
4368
4612
|
}
|
|
4369
4613
|
return infos;
|
|
4370
4614
|
}
|
|
4615
|
+
async drainEvents(input) {
|
|
4616
|
+
const controller = this.requirePage(input.pageRef);
|
|
4617
|
+
return mergeDistinctStepEvents([
|
|
4618
|
+
...this.drainQueuedEvents(input.pageRef),
|
|
4619
|
+
...await this.drainInstrumentedRuntimeEvents(controller)
|
|
4620
|
+
]);
|
|
4621
|
+
}
|
|
4371
4622
|
async listFrames(input) {
|
|
4372
4623
|
const controller = this.requirePage(input.pageRef);
|
|
4373
4624
|
await this.flushDomUpdateTask(controller);
|
|
@@ -4419,6 +4670,12 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
4419
4670
|
(contentDocIndex) => resolveCapturedContentDocumentRef(controller.framesByCdpId, captured, contentDocIndex)
|
|
4420
4671
|
);
|
|
4421
4672
|
}
|
|
4673
|
+
async getActionBoundarySnapshot(input) {
|
|
4674
|
+
const controller = this.requirePage(input.pageRef);
|
|
4675
|
+
await this.flushPendingPageTasks(controller.sessionRef);
|
|
4676
|
+
await this.flushDomUpdateTask(controller);
|
|
4677
|
+
return this.actionSettler.captureSnapshot(controller);
|
|
4678
|
+
}
|
|
4422
4679
|
async waitForVisualStability(input) {
|
|
4423
4680
|
const controller = this.requirePage(input.pageRef);
|
|
4424
4681
|
await this.flushDomUpdateTask(controller);
|
|
@@ -4429,6 +4686,21 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
4429
4686
|
});
|
|
4430
4687
|
await this.flushDomUpdateTask(controller);
|
|
4431
4688
|
}
|
|
4689
|
+
async waitForPostLoadQuiet(input) {
|
|
4690
|
+
const controller = this.requirePage(input.pageRef);
|
|
4691
|
+
await this.flushPendingPageTasks(controller.sessionRef);
|
|
4692
|
+
await this.actionSettler.waitForPostLoadQuiet({
|
|
4693
|
+
controller,
|
|
4694
|
+
timeoutMs: clampPlaywrightActionSettleTimeout(input.timeoutMs),
|
|
4695
|
+
...input.quietMs === void 0 ? {} : { quietMs: input.quietMs },
|
|
4696
|
+
...input.captureWindowMs === void 0 ? {} : { captureWindowMs: input.captureWindowMs },
|
|
4697
|
+
...input.signal === void 0 ? {} : { signal: input.signal }
|
|
4698
|
+
});
|
|
4699
|
+
await this.flushPendingPageTasks(controller.sessionRef);
|
|
4700
|
+
if (controller.lifecycleState !== "closed") {
|
|
4701
|
+
await this.flushDomUpdateTask(controller);
|
|
4702
|
+
}
|
|
4703
|
+
}
|
|
4432
4704
|
async readText(input) {
|
|
4433
4705
|
const document = this.requireDocument(input.documentRef);
|
|
4434
4706
|
const controller = this.requirePage(document.pageRef);
|
|
@@ -4950,9 +5222,11 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
4950
5222
|
session.activePageRef = pageRef;
|
|
4951
5223
|
await cdp.send("Page.enable", { enableFileChooserOpenedEvent: true });
|
|
4952
5224
|
await cdp.send("Network.enable");
|
|
5225
|
+
await cdp.send("Runtime.enable");
|
|
4953
5226
|
await cdp.send("DOM.enable", { includeWhitespace: "none" });
|
|
4954
5227
|
await cdp.send("DOMStorage.enable");
|
|
4955
5228
|
await cdp.send("DOM.getDocument", { depth: 0 });
|
|
5229
|
+
await this.installRuntimeEventRecorder(page);
|
|
4956
5230
|
await this.actionSettler.installTracker(controller);
|
|
4957
5231
|
cdp.on(
|
|
4958
5232
|
"Page.frameAttached",
|
|
@@ -5028,9 +5302,19 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
5028
5302
|
"DOM.documentUpdated",
|
|
5029
5303
|
() => this.runControllerEvent(controller, () => this.handleDocumentUpdated(controller))
|
|
5030
5304
|
);
|
|
5031
|
-
|
|
5032
|
-
"
|
|
5033
|
-
(
|
|
5305
|
+
cdp.on(
|
|
5306
|
+
"Runtime.consoleAPICalled",
|
|
5307
|
+
(payload) => this.runControllerEvent(
|
|
5308
|
+
controller,
|
|
5309
|
+
() => this.handleRuntimeConsole(controller, payload)
|
|
5310
|
+
)
|
|
5311
|
+
);
|
|
5312
|
+
cdp.on(
|
|
5313
|
+
"Runtime.exceptionThrown",
|
|
5314
|
+
(payload) => this.runControllerEvent(
|
|
5315
|
+
controller,
|
|
5316
|
+
() => this.handleRuntimeException(controller, payload)
|
|
5317
|
+
)
|
|
5034
5318
|
);
|
|
5035
5319
|
page.on(
|
|
5036
5320
|
"popup",
|
|
@@ -5057,10 +5341,6 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
5057
5341
|
"download",
|
|
5058
5342
|
(download) => this.runControllerEvent(controller, () => this.handleDownload(controller, download))
|
|
5059
5343
|
);
|
|
5060
|
-
page.on(
|
|
5061
|
-
"pageerror",
|
|
5062
|
-
(error) => this.runControllerEvent(controller, () => this.handlePageError(controller, error))
|
|
5063
|
-
);
|
|
5064
5344
|
page.on(
|
|
5065
5345
|
"request",
|
|
5066
5346
|
(request) => this.runControllerEvent(controller, () => this.handlePlaywrightRequest(controller, request))
|
|
@@ -5072,6 +5352,10 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
5072
5352
|
() => this.handlePlaywrightResponse(controller, response)
|
|
5073
5353
|
)
|
|
5074
5354
|
);
|
|
5355
|
+
page.on(
|
|
5356
|
+
"domcontentloaded",
|
|
5357
|
+
() => this.runControllerEvent(controller, () => this.handlePageDomContentLoaded(controller))
|
|
5358
|
+
);
|
|
5075
5359
|
page.on("close", () => this.handleUnexpectedPageClose(controller));
|
|
5076
5360
|
const frameTree = await cdp.send("Page.getFrameTree");
|
|
5077
5361
|
this.syncFrameTree(controller, frameTree.frameTree);
|
|
@@ -5124,6 +5408,7 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
5124
5408
|
documentRef,
|
|
5125
5409
|
documentEpoch: createDocumentEpoch(0),
|
|
5126
5410
|
url: "about:blank",
|
|
5411
|
+
domContentLoadedAt: void 0,
|
|
5127
5412
|
parentDocumentRef: parent?.currentDocument.documentRef,
|
|
5128
5413
|
nodeRefsByBackendNodeId: /* @__PURE__ */ new Map(),
|
|
5129
5414
|
backendNodeIdsByNodeRef: /* @__PURE__ */ new Map(),
|
|
@@ -5182,6 +5467,7 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
5182
5467
|
documentRef: nextDocumentRef,
|
|
5183
5468
|
documentEpoch: createDocumentEpoch(0),
|
|
5184
5469
|
url: combineFrameUrl(frame.url, frame.urlFragment),
|
|
5470
|
+
domContentLoadedAt: void 0,
|
|
5185
5471
|
parentDocumentRef: parent?.currentDocument.documentRef,
|
|
5186
5472
|
nodeRefsByBackendNodeId: /* @__PURE__ */ new Map(),
|
|
5187
5473
|
backendNodeIdsByNodeRef: /* @__PURE__ */ new Map(),
|
|
@@ -5211,6 +5497,13 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
5211
5497
|
handleDocumentUpdated(controller) {
|
|
5212
5498
|
this.queueDocumentReconciliation(controller);
|
|
5213
5499
|
}
|
|
5500
|
+
handlePageDomContentLoaded(controller) {
|
|
5501
|
+
const mainFrame = controller.mainFrameRef === void 0 ? void 0 : this.frames.get(controller.mainFrameRef);
|
|
5502
|
+
if (mainFrame === void 0) {
|
|
5503
|
+
return;
|
|
5504
|
+
}
|
|
5505
|
+
mainFrame.currentDocument.domContentLoadedAt = Date.now();
|
|
5506
|
+
}
|
|
5214
5507
|
syncFrameTree(controller, tree) {
|
|
5215
5508
|
const visit = (node, parentFrameRef) => {
|
|
5216
5509
|
const existing = controller.framesByCdpId.get(node.frame.id);
|
|
@@ -5224,6 +5517,7 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
5224
5517
|
documentRef,
|
|
5225
5518
|
documentEpoch: createDocumentEpoch(0),
|
|
5226
5519
|
url: combineFrameUrl(node.frame.url, node.frame.urlFragment),
|
|
5520
|
+
domContentLoadedAt: void 0,
|
|
5227
5521
|
parentDocumentRef: parentFrameRef === void 0 ? void 0 : this.requireFrame(parentFrameRef).currentDocument.documentRef,
|
|
5228
5522
|
nodeRefsByBackendNodeId: /* @__PURE__ */ new Map(),
|
|
5229
5523
|
backendNodeIdsByNodeRef: /* @__PURE__ */ new Map(),
|
|
@@ -5282,19 +5576,20 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
5282
5576
|
}
|
|
5283
5577
|
}
|
|
5284
5578
|
}
|
|
5285
|
-
|
|
5579
|
+
handleRuntimeConsole(controller, payload) {
|
|
5580
|
+
const callFrame = payload.stackTrace?.callFrames?.[0];
|
|
5286
5581
|
this.queueEvent(
|
|
5287
5582
|
controller.pageRef,
|
|
5288
5583
|
this.createEvent({
|
|
5289
5584
|
kind: "console",
|
|
5290
5585
|
sessionRef: controller.sessionRef,
|
|
5291
5586
|
pageRef: controller.pageRef,
|
|
5292
|
-
level:
|
|
5293
|
-
text:
|
|
5587
|
+
level: normalizeRuntimeConsoleLevel(payload.type),
|
|
5588
|
+
text: formatRuntimeConsoleText(payload),
|
|
5294
5589
|
location: {
|
|
5295
|
-
url:
|
|
5296
|
-
lineNumber:
|
|
5297
|
-
columnNumber:
|
|
5590
|
+
url: callFrame?.url ?? "",
|
|
5591
|
+
lineNumber: callFrame?.lineNumber ?? 0,
|
|
5592
|
+
columnNumber: callFrame?.columnNumber ?? 0
|
|
5298
5593
|
}
|
|
5299
5594
|
})
|
|
5300
5595
|
);
|
|
@@ -5375,15 +5670,18 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
5375
5670
|
})
|
|
5376
5671
|
);
|
|
5377
5672
|
}
|
|
5378
|
-
|
|
5673
|
+
handleRuntimeException(controller, payload) {
|
|
5674
|
+
const details = payload.exceptionDetails;
|
|
5675
|
+
const message = formatRuntimeExceptionMessage(details);
|
|
5676
|
+
const stack = formatRuntimeExceptionStack(details);
|
|
5379
5677
|
this.queueEvent(
|
|
5380
5678
|
controller.pageRef,
|
|
5381
5679
|
this.createEvent({
|
|
5382
5680
|
kind: "page-error",
|
|
5383
5681
|
sessionRef: controller.sessionRef,
|
|
5384
5682
|
pageRef: controller.pageRef,
|
|
5385
|
-
message
|
|
5386
|
-
...
|
|
5683
|
+
message,
|
|
5684
|
+
...stack === void 0 ? {} : { stack }
|
|
5387
5685
|
})
|
|
5388
5686
|
);
|
|
5389
5687
|
}
|
|
@@ -6105,10 +6403,11 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
6105
6403
|
}
|
|
6106
6404
|
}
|
|
6107
6405
|
createEvent(value) {
|
|
6406
|
+
const { timestamp, ...event } = value;
|
|
6108
6407
|
return {
|
|
6109
|
-
...
|
|
6408
|
+
...event,
|
|
6110
6409
|
eventId: `event:${++this.eventCounter}`,
|
|
6111
|
-
timestamp: Date.now()
|
|
6410
|
+
timestamp: timestamp ?? Date.now()
|
|
6112
6411
|
};
|
|
6113
6412
|
}
|
|
6114
6413
|
queueEvent(pageRef, event) {
|
|
@@ -6118,6 +6417,37 @@ var PlaywrightBrowserCoreEngine = class _PlaywrightBrowserCoreEngine {
|
|
|
6118
6417
|
}
|
|
6119
6418
|
controller.queuedEvents.push(event);
|
|
6120
6419
|
}
|
|
6420
|
+
async installRuntimeEventRecorder(page) {
|
|
6421
|
+
await page.addInitScript({
|
|
6422
|
+
content: PLAYWRIGHT_RUNTIME_EVENT_RECORDER_SOURCE
|
|
6423
|
+
});
|
|
6424
|
+
await page.evaluate(PLAYWRIGHT_RUNTIME_EVENT_RECORDER_SOURCE).catch(() => void 0);
|
|
6425
|
+
}
|
|
6426
|
+
async drainInstrumentedRuntimeEvents(controller) {
|
|
6427
|
+
const recorded = await Promise.all(
|
|
6428
|
+
controller.page.frames().map(async (frame) => {
|
|
6429
|
+
const events = await frame.evaluate(() => {
|
|
6430
|
+
const recorder = globalThis.__opensteerRuntimeEventRecorder;
|
|
6431
|
+
return recorder?.drain?.() ?? [];
|
|
6432
|
+
}).catch(() => []);
|
|
6433
|
+
return events;
|
|
6434
|
+
})
|
|
6435
|
+
);
|
|
6436
|
+
return mergeDistinctStepEvents(
|
|
6437
|
+
recorded.flatMap(
|
|
6438
|
+
(events) => events.map(
|
|
6439
|
+
(event) => this.createEvent({
|
|
6440
|
+
kind: "page-error",
|
|
6441
|
+
sessionRef: controller.sessionRef,
|
|
6442
|
+
pageRef: controller.pageRef,
|
|
6443
|
+
message: event.message ?? "Uncaught exception",
|
|
6444
|
+
...event.stack === void 0 ? {} : { stack: event.stack },
|
|
6445
|
+
timestamp: event.timestamp
|
|
6446
|
+
})
|
|
6447
|
+
)
|
|
6448
|
+
)
|
|
6449
|
+
);
|
|
6450
|
+
}
|
|
6121
6451
|
drainQueuedEvents(pageRef) {
|
|
6122
6452
|
const controller = this.requirePage(pageRef);
|
|
6123
6453
|
const events = controller.queuedEvents.splice(0, controller.queuedEvents.length);
|
|
@@ -6364,6 +6694,104 @@ function withTimeout(promise, timeoutMs) {
|
|
|
6364
6694
|
})
|
|
6365
6695
|
]);
|
|
6366
6696
|
}
|
|
6697
|
+
function formatRuntimeConsoleText(payload) {
|
|
6698
|
+
const parts = (payload.args ?? []).map((arg) => formatRuntimeRemoteObject(arg)).filter((value) => value.length > 0);
|
|
6699
|
+
if (parts.length > 0) {
|
|
6700
|
+
return parts.join(" ");
|
|
6701
|
+
}
|
|
6702
|
+
return payload.type?.trim() || "console";
|
|
6703
|
+
}
|
|
6704
|
+
function normalizeRuntimeConsoleLevel(value) {
|
|
6705
|
+
switch (value) {
|
|
6706
|
+
case "warning":
|
|
6707
|
+
case "debug":
|
|
6708
|
+
case "info":
|
|
6709
|
+
case "error":
|
|
6710
|
+
case "trace":
|
|
6711
|
+
return normalizeConsoleLevel(value);
|
|
6712
|
+
default:
|
|
6713
|
+
return "log";
|
|
6714
|
+
}
|
|
6715
|
+
}
|
|
6716
|
+
function formatRuntimeExceptionMessage(details) {
|
|
6717
|
+
const description = details?.exception?.description?.trim();
|
|
6718
|
+
if (description) {
|
|
6719
|
+
const firstLine = description.split("\n")[0]?.trim() ?? "";
|
|
6720
|
+
if (firstLine.startsWith("Error: ")) {
|
|
6721
|
+
return firstLine.slice("Error: ".length);
|
|
6722
|
+
}
|
|
6723
|
+
return firstLine || description;
|
|
6724
|
+
}
|
|
6725
|
+
const value = details?.exception?.value;
|
|
6726
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
6727
|
+
return value.trim();
|
|
6728
|
+
}
|
|
6729
|
+
return details?.text?.trim() || "Uncaught exception";
|
|
6730
|
+
}
|
|
6731
|
+
function formatRuntimeExceptionStack(details) {
|
|
6732
|
+
const description = details?.exception?.description?.trim();
|
|
6733
|
+
if (description && description.includes("\n")) {
|
|
6734
|
+
return description;
|
|
6735
|
+
}
|
|
6736
|
+
const frames = details?.stackTrace?.callFrames;
|
|
6737
|
+
if (!frames || frames.length === 0) {
|
|
6738
|
+
return void 0;
|
|
6739
|
+
}
|
|
6740
|
+
return frames.map((frame) => {
|
|
6741
|
+
const url = frame.url ?? "<anonymous>";
|
|
6742
|
+
const lineNumber = frame.lineNumber ?? 0;
|
|
6743
|
+
const columnNumber = frame.columnNumber ?? 0;
|
|
6744
|
+
return ` at ${url}:${lineNumber}:${columnNumber}`;
|
|
6745
|
+
}).join("\n");
|
|
6746
|
+
}
|
|
6747
|
+
function formatRuntimeRemoteObject(object) {
|
|
6748
|
+
if (object.unserializableValue !== void 0) {
|
|
6749
|
+
return object.unserializableValue;
|
|
6750
|
+
}
|
|
6751
|
+
if (object.value !== void 0) {
|
|
6752
|
+
return typeof object.value === "string" ? object.value : JSON.stringify(object.value);
|
|
6753
|
+
}
|
|
6754
|
+
if (object.description !== void 0 && object.description.length > 0) {
|
|
6755
|
+
return object.description;
|
|
6756
|
+
}
|
|
6757
|
+
const previewParts = object.preview?.properties?.map((property) => {
|
|
6758
|
+
if (!property.name) {
|
|
6759
|
+
return "";
|
|
6760
|
+
}
|
|
6761
|
+
return property.value === void 0 ? property.name : `${property.name}: ${property.value}`;
|
|
6762
|
+
}).filter((value) => value.length > 0) ?? [];
|
|
6763
|
+
return previewParts.join(", ");
|
|
6764
|
+
}
|
|
6765
|
+
function mergeDistinctStepEvents(events) {
|
|
6766
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6767
|
+
const merged = [];
|
|
6768
|
+
for (const event of events) {
|
|
6769
|
+
const fingerprint = stepEventFingerprint(event);
|
|
6770
|
+
if (seen.has(fingerprint)) {
|
|
6771
|
+
continue;
|
|
6772
|
+
}
|
|
6773
|
+
seen.add(fingerprint);
|
|
6774
|
+
merged.push(event);
|
|
6775
|
+
}
|
|
6776
|
+
return merged;
|
|
6777
|
+
}
|
|
6778
|
+
function stepEventFingerprint(event) {
|
|
6779
|
+
switch (event.kind) {
|
|
6780
|
+
case "console":
|
|
6781
|
+
return [
|
|
6782
|
+
event.kind,
|
|
6783
|
+
event.level,
|
|
6784
|
+
event.text,
|
|
6785
|
+
event.location?.url ?? "",
|
|
6786
|
+
event.location?.lineNumber ?? "",
|
|
6787
|
+
event.location?.columnNumber ?? ""
|
|
6788
|
+
].join("|");
|
|
6789
|
+
case "page-error":
|
|
6790
|
+
return [event.kind, event.message, event.stack ?? ""].join("|");
|
|
6791
|
+
default:
|
|
6792
|
+
return event.eventId;
|
|
6793
|
+
}
|
|
6794
|
+
}
|
|
6367
6795
|
|
|
6368
6796
|
export { PlaywrightBrowserCoreEngine, capturePlaywrightStorageOrigins, connectPlaywrightChromiumBrowser, createPlaywrightBrowserCoreEngine, disconnectPlaywrightChromiumBrowser };
|
|
6369
6797
|
//# sourceMappingURL=index.js.map
|