playwright-core 1.54.0-alpha-2025-06-23 → 1.54.0-alpha-2025-06-25
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/ThirdPartyNotices.txt +3 -3
- package/browsers.json +4 -4
- package/lib/cli/programWithTestStub.js +1 -1
- package/lib/client/elementHandle.js +0 -4
- package/lib/client/locator.js +2 -1
- package/lib/generated/injectedScriptSource.js +1 -1
- package/lib/protocol/validator.js +6 -4
- package/lib/remote/playwrightServer.js +5 -9
- package/lib/server/android/android.js +2 -2
- package/lib/server/bidi/bidiPage.js +2 -2
- package/lib/server/browser.js +1 -1
- package/lib/server/browserContext.js +3 -3
- package/lib/server/browserType.js +3 -3
- package/lib/server/chromium/chromium.js +7 -9
- package/lib/server/chromium/crPage.js +2 -3
- package/lib/server/chromium/videoRecorder.js +1 -1
- package/lib/server/dispatchers/elementHandlerDispatcher.js +0 -3
- package/lib/server/dispatchers/frameDispatcher.js +3 -0
- package/lib/server/dispatchers/localUtilsDispatcher.js +2 -3
- package/lib/server/dom.js +20 -50
- package/lib/server/electron/electron.js +1 -1
- package/lib/server/fetch.js +1 -1
- package/lib/server/firefox/ffPage.js +2 -2
- package/lib/server/frames.js +77 -58
- package/lib/server/input.js +11 -11
- package/lib/server/page.js +5 -8
- package/lib/server/progress.js +41 -21
- package/lib/server/recorder/recorderApp.js +1 -1
- package/lib/server/registry/index.js +1 -1
- package/lib/server/registry/oopDownloadBrowserMain.js +1 -1
- package/lib/server/screenshotter.js +1 -1
- package/lib/server/trace/viewer/traceViewer.js +1 -1
- package/lib/server/transport.js +0 -2
- package/lib/server/utils/network.js +13 -14
- package/lib/server/webkit/wkPage.js +1 -1
- package/lib/utils/isomorphic/protocolMetainfo.js +1 -1
- package/lib/utilsBundleImpl/index.js +160 -150
- package/lib/vite/traceViewer/assets/{codeMirrorModule--amfWN3K.js → codeMirrorModule-KhY1IY1h.js} +1 -1
- package/lib/vite/traceViewer/assets/{defaultSettingsView-BFAIqAv2.js → defaultSettingsView-h9mbAVJF.js} +45 -45
- package/lib/vite/traceViewer/{index.amRtOpxT.js → index.Ckw7w8kC.js} +1 -1
- package/lib/vite/traceViewer/index.html +2 -2
- package/lib/vite/traceViewer/uiMode.html +2 -2
- package/lib/vite/traceViewer/{uiMode.hufuL2u6.js → uiMode.wzqlDRzc.js} +1 -1
- package/package.json +1 -1
package/lib/server/frames.js
CHANGED
|
@@ -484,7 +484,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
484
484
|
}));
|
|
485
485
|
}
|
|
486
486
|
redirectNavigation(url, documentId, referer) {
|
|
487
|
-
const controller = new import_progress.ProgressController((0, import_instrumentation.serverSideCallMetadata)(), this
|
|
487
|
+
const controller = new import_progress.ProgressController((0, import_instrumentation.serverSideCallMetadata)(), this);
|
|
488
488
|
const data = {
|
|
489
489
|
url,
|
|
490
490
|
gotoPromise: controller.run((progress) => this.gotoImpl(progress, url, { referer }), 0)
|
|
@@ -493,7 +493,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
493
493
|
data.gotoPromise.finally(() => this._redirectedNavigations.delete(documentId));
|
|
494
494
|
}
|
|
495
495
|
async goto(metadata, url, options) {
|
|
496
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
496
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
497
497
|
return controller.run((progress) => {
|
|
498
498
|
const constructedNavigationURL = (0, import_utils.constructURLBasedOnBaseURL)(this._page.browserContext._options.baseURL, url);
|
|
499
499
|
return this.raceNavigationAction(progress, async () => this.gotoImpl(progress, constructedNavigationURL, options));
|
|
@@ -603,7 +603,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
603
603
|
return this.selectors.query(selector, options);
|
|
604
604
|
}
|
|
605
605
|
async waitForSelector(metadata, selector, options, scope) {
|
|
606
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
606
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
607
607
|
return controller.run(async (progress) => {
|
|
608
608
|
if (options.visibility)
|
|
609
609
|
throw new Error("options.visibility is not supported, did you mean options.state?");
|
|
@@ -720,7 +720,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
720
720
|
}
|
|
721
721
|
}
|
|
722
722
|
async setContent(metadata, html, options) {
|
|
723
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
723
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
724
724
|
return controller.run(async (progress) => {
|
|
725
725
|
await this.raceNavigationAction(progress, async () => {
|
|
726
726
|
const waitUntil = options.waitUntil === void 0 ? "load" : options.waitUntil;
|
|
@@ -953,19 +953,19 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
953
953
|
});
|
|
954
954
|
}
|
|
955
955
|
async click(metadata, selector, options) {
|
|
956
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
956
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
957
957
|
return controller.run(async (progress) => {
|
|
958
958
|
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._click(progress, { ...options, waitAfter: !options.noWaitAfter })));
|
|
959
959
|
}, options.timeout);
|
|
960
960
|
}
|
|
961
961
|
async dblclick(metadata, selector, options) {
|
|
962
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
962
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
963
963
|
return controller.run(async (progress) => {
|
|
964
964
|
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._dblclick(progress, options)));
|
|
965
965
|
}, options.timeout);
|
|
966
966
|
}
|
|
967
967
|
async dragAndDrop(metadata, source, target, options) {
|
|
968
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
968
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
969
969
|
await controller.run(async (progress) => {
|
|
970
970
|
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, source, options.strict, !options.force, async (handle) => {
|
|
971
971
|
return handle._retryPointerAction(progress, "move and down", false, async (point) => {
|
|
@@ -990,7 +990,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
990
990
|
}, options.timeout);
|
|
991
991
|
}
|
|
992
992
|
async tap(metadata, selector, options) {
|
|
993
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
993
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
994
994
|
return controller.run(async (progress) => {
|
|
995
995
|
if (!this._page.browserContext._options.hasTouch)
|
|
996
996
|
throw new Error("The page does not support tap. Use hasTouch context option to enable touch support.");
|
|
@@ -998,23 +998,52 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
998
998
|
}, options.timeout);
|
|
999
999
|
}
|
|
1000
1000
|
async fill(metadata, selector, value, options) {
|
|
1001
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
1001
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1002
1002
|
return controller.run(async (progress) => {
|
|
1003
1003
|
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._fill(progress, value, options)));
|
|
1004
1004
|
}, options.timeout);
|
|
1005
1005
|
}
|
|
1006
1006
|
async focus(metadata, selector, options) {
|
|
1007
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
1007
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1008
1008
|
await controller.run(async (progress) => {
|
|
1009
1009
|
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true, (handle) => handle._focus(progress)));
|
|
1010
1010
|
}, options.timeout);
|
|
1011
1011
|
}
|
|
1012
1012
|
async blur(metadata, selector, options) {
|
|
1013
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
1013
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1014
1014
|
await controller.run(async (progress) => {
|
|
1015
1015
|
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true, (handle) => handle._blur(progress)));
|
|
1016
1016
|
}, options.timeout);
|
|
1017
1017
|
}
|
|
1018
|
+
async generateLocatorString(metadata, selector) {
|
|
1019
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1020
|
+
return controller.run(async (progress) => {
|
|
1021
|
+
const element = await progress.race(this.selectors.query(selector));
|
|
1022
|
+
if (!element)
|
|
1023
|
+
throw new Error(`No element matching ${this._asLocator(selector)}`);
|
|
1024
|
+
const generated = await progress.race(element.evaluateInUtility(async ([injected, node]) => {
|
|
1025
|
+
return injected.generateSelectorSimple(node);
|
|
1026
|
+
}, {}));
|
|
1027
|
+
if (!generated)
|
|
1028
|
+
throw new Error(`Unable to generate locator for ${this._asLocator(selector)}`);
|
|
1029
|
+
let frame = element._frame;
|
|
1030
|
+
const result = [generated];
|
|
1031
|
+
while (frame?.parentFrame()) {
|
|
1032
|
+
const frameElement = await progress.race(frame.frameElement());
|
|
1033
|
+
if (frameElement) {
|
|
1034
|
+
const generated2 = await progress.race(frameElement.evaluateInUtility(async ([injected, node]) => {
|
|
1035
|
+
return injected.generateSelectorSimple(node);
|
|
1036
|
+
}, {}));
|
|
1037
|
+
frameElement.dispose();
|
|
1038
|
+
if (generated2 === "error:notconnected" || !generated2)
|
|
1039
|
+
throw new Error(`Unable to generate locator for ${this._asLocator(selector)}`);
|
|
1040
|
+
result.push(generated2);
|
|
1041
|
+
}
|
|
1042
|
+
frame = frame.parentFrame();
|
|
1043
|
+
}
|
|
1044
|
+
return (0, import_utils.asLocator)(this._page.browserContext._browser.sdkLanguage(), result.reverse().join(" >> internal:control=enter-frame >> "));
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1018
1047
|
async textContent(metadata, selector, options, scope) {
|
|
1019
1048
|
return this._callOnElementOnceMatches(metadata, selector, (injected, element) => element.textContent, void 0, options, scope);
|
|
1020
1049
|
}
|
|
@@ -1065,7 +1094,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1065
1094
|
return result.matches;
|
|
1066
1095
|
}
|
|
1067
1096
|
async isVisible(metadata, selector, options = {}, scope) {
|
|
1068
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
1097
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1069
1098
|
return controller.run(async (progress) => {
|
|
1070
1099
|
progress.log(` checking visibility of ${this._asLocator(selector)}`);
|
|
1071
1100
|
return await this.isVisibleInternal(progress, selector, options, scope);
|
|
@@ -1103,54 +1132,54 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1103
1132
|
return this._elementState(metadata, selector, "checked", options, scope);
|
|
1104
1133
|
}
|
|
1105
1134
|
async hover(metadata, selector, options) {
|
|
1106
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
1135
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1107
1136
|
return controller.run(async (progress) => {
|
|
1108
1137
|
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._hover(progress, options)));
|
|
1109
1138
|
}, options.timeout);
|
|
1110
1139
|
}
|
|
1111
1140
|
async selectOption(metadata, selector, elements, values, options) {
|
|
1112
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
1141
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1113
1142
|
return controller.run(async (progress) => {
|
|
1114
1143
|
return await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._selectOption(progress, elements, values, options));
|
|
1115
1144
|
}, options.timeout);
|
|
1116
1145
|
}
|
|
1117
1146
|
async setInputFiles(metadata, selector, params) {
|
|
1118
1147
|
const inputFileItems = await (0, import_fileUploadUtils.prepareFilesForUpload)(this, params);
|
|
1119
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
1148
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1120
1149
|
return controller.run(async (progress) => {
|
|
1121
1150
|
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, params.strict, true, (handle) => handle._setInputFiles(progress, inputFileItems)));
|
|
1122
1151
|
}, params.timeout);
|
|
1123
1152
|
}
|
|
1124
1153
|
async type(metadata, selector, text, options) {
|
|
1125
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
1154
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1126
1155
|
return controller.run(async (progress) => {
|
|
1127
1156
|
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true, (handle) => handle._type(progress, text, options)));
|
|
1128
1157
|
}, options.timeout);
|
|
1129
1158
|
}
|
|
1130
1159
|
async press(metadata, selector, key, options) {
|
|
1131
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
1160
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1132
1161
|
return controller.run(async (progress) => {
|
|
1133
1162
|
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true, (handle) => handle._press(progress, key, options)));
|
|
1134
1163
|
}, options.timeout);
|
|
1135
1164
|
}
|
|
1136
1165
|
async check(metadata, selector, options) {
|
|
1137
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
1166
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1138
1167
|
return controller.run(async (progress) => {
|
|
1139
1168
|
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._setChecked(progress, true, options)));
|
|
1140
1169
|
}, options.timeout);
|
|
1141
1170
|
}
|
|
1142
1171
|
async uncheck(metadata, selector, options) {
|
|
1143
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
1172
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1144
1173
|
return controller.run(async (progress) => {
|
|
1145
1174
|
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._setChecked(progress, false, options)));
|
|
1146
1175
|
}, options.timeout);
|
|
1147
1176
|
}
|
|
1148
1177
|
async waitForTimeout(metadata, timeout) {
|
|
1149
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
1178
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1150
1179
|
return controller.run((progress) => progress.wait(timeout));
|
|
1151
1180
|
}
|
|
1152
1181
|
async ariaSnapshot(metadata, selector, options) {
|
|
1153
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
1182
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1154
1183
|
return controller.run(async (progress) => {
|
|
1155
1184
|
return await this._retryWithProgressIfNotConnected(progress, selector, true, true, (handle) => progress.race(handle.ariaSnapshot(options)));
|
|
1156
1185
|
}, options.timeout);
|
|
@@ -1162,43 +1191,32 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1162
1191
|
return result;
|
|
1163
1192
|
}
|
|
1164
1193
|
async _expectImpl(metadata, selector, options) {
|
|
1194
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1165
1195
|
const lastIntermediateResult = { isSet: false };
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
progress.log(`waiting for ${this._asLocator(selector)}`);
|
|
1173
|
-
await this._page.performActionPreChecks(progress);
|
|
1174
|
-
}, timeout);
|
|
1196
|
+
return await controller.run(async (progress) => {
|
|
1197
|
+
progress.log(`${(0, import_utils.renderTitleForCall)(metadata)}${options.timeout ? ` with timeout ${options.timeout}ms` : ""}`);
|
|
1198
|
+
if (selector)
|
|
1199
|
+
progress.log(`waiting for ${this._asLocator(selector)}`);
|
|
1200
|
+
await this._page.performActionPreChecks(progress);
|
|
1201
|
+
progress.legacyDisableTimeout();
|
|
1175
1202
|
try {
|
|
1176
|
-
const resultOneShot = await
|
|
1177
|
-
return await this._expectInternal(progress, selector, options, lastIntermediateResult);
|
|
1178
|
-
});
|
|
1203
|
+
const resultOneShot = await this._expectInternal(progress, selector, options, lastIntermediateResult, true);
|
|
1179
1204
|
if (resultOneShot.matches !== options.isNot)
|
|
1180
1205
|
return resultOneShot;
|
|
1181
1206
|
} catch (e) {
|
|
1182
1207
|
if (this.isNonRetriableError(e))
|
|
1183
1208
|
throw e;
|
|
1184
1209
|
}
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
return
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
if (matches === options.isNot) {
|
|
1196
|
-
return continuePolling;
|
|
1197
|
-
}
|
|
1198
|
-
return { matches, received };
|
|
1199
|
-
});
|
|
1200
|
-
}, timeout);
|
|
1201
|
-
} catch (e) {
|
|
1210
|
+
progress.legacyEnableTimeout();
|
|
1211
|
+
return await this.retryWithProgressAndTimeouts(progress, [100, 250, 500, 1e3], async (continuePolling) => {
|
|
1212
|
+
await this._page.performActionPreChecks(progress);
|
|
1213
|
+
const { matches, received } = await this._expectInternal(progress, selector, options, lastIntermediateResult, false);
|
|
1214
|
+
if (matches === options.isNot) {
|
|
1215
|
+
return continuePolling;
|
|
1216
|
+
}
|
|
1217
|
+
return { matches, received };
|
|
1218
|
+
});
|
|
1219
|
+
}, options.timeout).catch((e) => {
|
|
1202
1220
|
if (js.isJavaScriptErrorInEvaluate(e) || (0, import_selectorParser.isInvalidSelectorError)(e))
|
|
1203
1221
|
throw e;
|
|
1204
1222
|
const result = { matches: options.isNot, log: (0, import_callLog.compressCallLog)(metadata.log) };
|
|
@@ -1207,15 +1225,16 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1207
1225
|
if (e instanceof import_errors.TimeoutError)
|
|
1208
1226
|
result.timedOut = true;
|
|
1209
1227
|
return result;
|
|
1210
|
-
}
|
|
1228
|
+
});
|
|
1211
1229
|
}
|
|
1212
|
-
async _expectInternal(progress, selector, options, lastIntermediateResult) {
|
|
1213
|
-
const
|
|
1230
|
+
async _expectInternal(progress, selector, options, lastIntermediateResult, noAbort) {
|
|
1231
|
+
const race = (p) => noAbort ? p : progress.race(p);
|
|
1232
|
+
const selectorInFrame = selector ? await race(this.selectors.resolveFrameForSelector(selector, { strict: true })) : void 0;
|
|
1214
1233
|
const { frame, info } = selectorInFrame || { frame: this, info: void 0 };
|
|
1215
1234
|
const world = options.expression === "to.have.property" ? "main" : info?.world ?? "utility";
|
|
1216
|
-
const context = await
|
|
1217
|
-
const injected = await
|
|
1218
|
-
const { log, matches, received, missingReceived } = await
|
|
1235
|
+
const context = await race(frame._context(world));
|
|
1236
|
+
const injected = await race(context.injectedScript());
|
|
1237
|
+
const { log, matches, received, missingReceived } = await race(injected.evaluate(async (injected2, { info: info2, options: options2, callId }) => {
|
|
1219
1238
|
const elements = info2 ? injected2.querySelectorAll(info2.parsed, document) : [];
|
|
1220
1239
|
if (callId)
|
|
1221
1240
|
injected2.markTargetElements(new Set(elements), callId);
|
|
@@ -1240,7 +1259,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1240
1259
|
return { matches, received };
|
|
1241
1260
|
}
|
|
1242
1261
|
async waitForFunctionExpression(metadata, expression, isFunction, arg, options) {
|
|
1243
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
1262
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1244
1263
|
return controller.run((progress) => this.waitForFunctionExpressionImpl(progress, expression, isFunction, arg, options, "main"), options.timeout);
|
|
1245
1264
|
}
|
|
1246
1265
|
async waitForFunctionExpressionImpl(progress, expression, isFunction, arg, options, world = "main") {
|
|
@@ -1337,7 +1356,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1337
1356
|
this._parentFrame = null;
|
|
1338
1357
|
}
|
|
1339
1358
|
async _callOnElementOnceMatches(metadata, selector, body, taskData, options, scope) {
|
|
1340
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
1359
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
1341
1360
|
return controller.run(async (progress) => {
|
|
1342
1361
|
const callbackText = body.toString();
|
|
1343
1362
|
progress.log(`waiting for ${this._asLocator(selector)}`);
|
package/lib/server/input.js
CHANGED
|
@@ -49,7 +49,7 @@ class Keyboard {
|
|
|
49
49
|
this._page = page;
|
|
50
50
|
}
|
|
51
51
|
async down(metadata, key) {
|
|
52
|
-
const controller = new import_progress.ProgressController(metadata, this._page
|
|
52
|
+
const controller = new import_progress.ProgressController(metadata, this._page);
|
|
53
53
|
return controller.run((progress) => this._down(progress, key));
|
|
54
54
|
}
|
|
55
55
|
async _down(progress, key) {
|
|
@@ -71,7 +71,7 @@ class Keyboard {
|
|
|
71
71
|
return description;
|
|
72
72
|
}
|
|
73
73
|
async up(metadata, key) {
|
|
74
|
-
const controller = new import_progress.ProgressController(metadata, this._page
|
|
74
|
+
const controller = new import_progress.ProgressController(metadata, this._page);
|
|
75
75
|
return controller.run((progress) => this._up(progress, key));
|
|
76
76
|
}
|
|
77
77
|
async _up(progress, key) {
|
|
@@ -82,14 +82,14 @@ class Keyboard {
|
|
|
82
82
|
await this._raw.keyup(progress, this._pressedModifiers, key, description);
|
|
83
83
|
}
|
|
84
84
|
async insertText(metadata, text) {
|
|
85
|
-
const controller = new import_progress.ProgressController(metadata, this._page
|
|
85
|
+
const controller = new import_progress.ProgressController(metadata, this._page);
|
|
86
86
|
return controller.run((progress) => this._insertText(progress, text));
|
|
87
87
|
}
|
|
88
88
|
async _insertText(progress, text) {
|
|
89
89
|
await this._raw.sendText(progress, text);
|
|
90
90
|
}
|
|
91
91
|
async type(metadata, text, options) {
|
|
92
|
-
const controller = new import_progress.ProgressController(metadata, this._page
|
|
92
|
+
const controller = new import_progress.ProgressController(metadata, this._page);
|
|
93
93
|
return controller.run((progress) => this._type(progress, text, options));
|
|
94
94
|
}
|
|
95
95
|
async _type(progress, text, options) {
|
|
@@ -105,7 +105,7 @@ class Keyboard {
|
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
async press(metadata, key, options) {
|
|
108
|
-
const controller = new import_progress.ProgressController(metadata, this._page
|
|
108
|
+
const controller = new import_progress.ProgressController(metadata, this._page);
|
|
109
109
|
return controller.run((progress) => this._press(progress, key, options));
|
|
110
110
|
}
|
|
111
111
|
async _press(progress, key, options = {}) {
|
|
@@ -177,7 +177,7 @@ class Mouse {
|
|
|
177
177
|
return { x: this._x, y: this._y };
|
|
178
178
|
}
|
|
179
179
|
async move(metadata, x, y, options) {
|
|
180
|
-
const controller = new import_progress.ProgressController(metadata, this._page
|
|
180
|
+
const controller = new import_progress.ProgressController(metadata, this._page);
|
|
181
181
|
return controller.run((progress) => this._move(progress, x, y, options));
|
|
182
182
|
}
|
|
183
183
|
async _move(progress, x, y, options = {}) {
|
|
@@ -193,7 +193,7 @@ class Mouse {
|
|
|
193
193
|
}
|
|
194
194
|
}
|
|
195
195
|
async down(metadata, options) {
|
|
196
|
-
const controller = new import_progress.ProgressController(metadata, this._page
|
|
196
|
+
const controller = new import_progress.ProgressController(metadata, this._page);
|
|
197
197
|
return controller.run((progress) => this._down(progress, options));
|
|
198
198
|
}
|
|
199
199
|
async _down(progress, options = {}) {
|
|
@@ -203,7 +203,7 @@ class Mouse {
|
|
|
203
203
|
await this._raw.down(progress, this._x, this._y, this._lastButton, this._buttons, this._keyboard._modifiers(), clickCount);
|
|
204
204
|
}
|
|
205
205
|
async up(metadata, options) {
|
|
206
|
-
const controller = new import_progress.ProgressController(metadata, this._page
|
|
206
|
+
const controller = new import_progress.ProgressController(metadata, this._page);
|
|
207
207
|
return controller.run((progress) => this._up(progress, options));
|
|
208
208
|
}
|
|
209
209
|
async _up(progress, options = {}) {
|
|
@@ -213,7 +213,7 @@ class Mouse {
|
|
|
213
213
|
await this._raw.up(progress, this._x, this._y, button, this._buttons, this._keyboard._modifiers(), clickCount);
|
|
214
214
|
}
|
|
215
215
|
async click(metadata, x, y, options) {
|
|
216
|
-
const controller = new import_progress.ProgressController(metadata, this._page
|
|
216
|
+
const controller = new import_progress.ProgressController(metadata, this._page);
|
|
217
217
|
return controller.run((progress) => this._click(progress, x, y, options));
|
|
218
218
|
}
|
|
219
219
|
async _click(progress, x, y, options = {}) {
|
|
@@ -238,7 +238,7 @@ class Mouse {
|
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
240
|
async wheel(metadata, deltaX, deltaY) {
|
|
241
|
-
const controller = new import_progress.ProgressController(metadata, this._page
|
|
241
|
+
const controller = new import_progress.ProgressController(metadata, this._page);
|
|
242
242
|
return controller.run(async (progress) => {
|
|
243
243
|
await this._raw.wheel(progress, this._x, this._y, this._buttons, this._keyboard._modifiers(), deltaX, deltaY);
|
|
244
244
|
});
|
|
@@ -295,7 +295,7 @@ class Touchscreen {
|
|
|
295
295
|
this._page = page;
|
|
296
296
|
}
|
|
297
297
|
async tap(metadata, x, y) {
|
|
298
|
-
const controller = new import_progress.ProgressController(metadata, this._page
|
|
298
|
+
const controller = new import_progress.ProgressController(metadata, this._page);
|
|
299
299
|
return controller.run((progress) => this._tap(progress, x, y));
|
|
300
300
|
}
|
|
301
301
|
async _tap(progress, x, y) {
|
package/lib/server/page.js
CHANGED
|
@@ -249,7 +249,7 @@ class Page extends import_instrumentation.SdkObject {
|
|
|
249
249
|
this.emitOnContextOnceInitialized(import_browserContext.BrowserContext.Events.Console, message);
|
|
250
250
|
}
|
|
251
251
|
async reload(metadata, options) {
|
|
252
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
252
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
253
253
|
return controller.run((progress) => this.mainFrame().raceNavigationAction(progress, async () => {
|
|
254
254
|
const [response] = await Promise.all([
|
|
255
255
|
// Reload must be a new document, and should not be confused with a stray pushState.
|
|
@@ -260,7 +260,7 @@ class Page extends import_instrumentation.SdkObject {
|
|
|
260
260
|
}), options.timeout);
|
|
261
261
|
}
|
|
262
262
|
async goBack(metadata, options) {
|
|
263
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
263
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
264
264
|
return controller.run((progress) => this.mainFrame().raceNavigationAction(progress, async () => {
|
|
265
265
|
let error;
|
|
266
266
|
const waitPromise = this.mainFrame()._waitForNavigation(progress, false, options).catch((e) => {
|
|
@@ -280,7 +280,7 @@ class Page extends import_instrumentation.SdkObject {
|
|
|
280
280
|
}), options.timeout);
|
|
281
281
|
}
|
|
282
282
|
async goForward(metadata, options) {
|
|
283
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
283
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
284
284
|
return controller.run((progress) => this.mainFrame().raceNavigationAction(progress, async () => {
|
|
285
285
|
let error;
|
|
286
286
|
const waitPromise = this.mainFrame()._waitForNavigation(progress, false, options).catch((e) => {
|
|
@@ -321,9 +321,7 @@ class Page extends import_instrumentation.SdkObject {
|
|
|
321
321
|
}
|
|
322
322
|
async performActionPreChecks(progress) {
|
|
323
323
|
await this._performWaitForNavigationCheck(progress);
|
|
324
|
-
progress.throwIfAborted();
|
|
325
324
|
await this._performLocatorHandlersCheckpoint(progress);
|
|
326
|
-
progress.throwIfAborted();
|
|
327
325
|
await this._performWaitForNavigationCheck(progress);
|
|
328
326
|
}
|
|
329
327
|
async _performWaitForNavigationCheck(progress) {
|
|
@@ -355,7 +353,6 @@ class Page extends import_instrumentation.SdkObject {
|
|
|
355
353
|
++this._locatorHandlerRunningCounter;
|
|
356
354
|
progress.log(` found ${(0, import_utils2.asLocator)(this.browserContext._browser.sdkLanguage(), handler.selector)}, intercepting action to run the handler`);
|
|
357
355
|
const promise = handler.resolved.then(async () => {
|
|
358
|
-
progress.throwIfAborted();
|
|
359
356
|
if (!handler.noWaitAfter) {
|
|
360
357
|
progress.log(` locator handler has finished, waiting for ${(0, import_utils2.asLocator)(this.browserContext._browser.sdkLanguage(), handler.selector)} to be hidden`);
|
|
361
358
|
await this.mainFrame().waitForSelectorInternal(progress, handler.selector, false, { state: "hidden" });
|
|
@@ -450,7 +447,7 @@ class Page extends import_instrumentation.SdkObject {
|
|
|
450
447
|
return await this.screenshotter.screenshotPage(progress, options || {});
|
|
451
448
|
};
|
|
452
449
|
const comparator = (0, import_comparators.getComparator)("image/png");
|
|
453
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
450
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
454
451
|
if (!options.expected && options.isNot)
|
|
455
452
|
return { errorMessage: '"not" matcher requires expected result' };
|
|
456
453
|
try {
|
|
@@ -630,7 +627,7 @@ class Page extends import_instrumentation.SdkObject {
|
|
|
630
627
|
this._isServerSideOnly = true;
|
|
631
628
|
}
|
|
632
629
|
snapshotForAI(metadata) {
|
|
633
|
-
const controller = new import_progress.ProgressController(metadata, this
|
|
630
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
634
631
|
return controller.run(async (progress) => {
|
|
635
632
|
this.lastSnapshotFrameIds = [];
|
|
636
633
|
const snapshot = await snapshotFrameForAI(progress, this.mainFrame(), 0, this.lastSnapshotFrameIds);
|
package/lib/server/progress.js
CHANGED
|
@@ -26,7 +26,7 @@ var import_errors = require("./errors");
|
|
|
26
26
|
var import_utils = require("../utils");
|
|
27
27
|
var import_manualPromise = require("../utils/isomorphic/manualPromise");
|
|
28
28
|
class ProgressController {
|
|
29
|
-
constructor(metadata, sdkObject
|
|
29
|
+
constructor(metadata, sdkObject) {
|
|
30
30
|
this._forceAbortPromise = new import_manualPromise.ManualPromise();
|
|
31
31
|
this._donePromise = new import_manualPromise.ManualPromise();
|
|
32
32
|
// Cleanups to be run only in the case of abort.
|
|
@@ -38,8 +38,7 @@ class ProgressController {
|
|
|
38
38
|
// progress only finishes after the inner callback exits, guaranteeing no work after the timeout.
|
|
39
39
|
this._strictMode = false;
|
|
40
40
|
this._state = "before";
|
|
41
|
-
this.
|
|
42
|
-
this._strictMode = strictMode === "strict";
|
|
41
|
+
this._strictMode = !process.env.PLAYWRIGHT_LEGACY_TIMEOUTS;
|
|
43
42
|
this.metadata = metadata;
|
|
44
43
|
this.sdkObject = sdkObject;
|
|
45
44
|
this.instrumentation = sdkObject.instrumentation;
|
|
@@ -59,27 +58,44 @@ class ProgressController {
|
|
|
59
58
|
await this._donePromise;
|
|
60
59
|
}
|
|
61
60
|
async run(task, timeout) {
|
|
62
|
-
this._deadline = timeout ? (0, import_utils.monotonicTime)() + timeout : 0;
|
|
63
61
|
(0, import_utils.assert)(this._state === "before");
|
|
64
62
|
this._state = "running";
|
|
65
63
|
this.sdkObject.attribution.context?._activeProgressControllers.add(this);
|
|
64
|
+
const deadline = timeout ? Math.min((0, import_utils.monotonicTime)() + timeout, 2147483647) : 0;
|
|
65
|
+
const timeoutError = new import_errors.TimeoutError(`Timeout ${timeout}ms exceeded.`);
|
|
66
|
+
let timer;
|
|
67
|
+
const startTimer = () => {
|
|
68
|
+
if (!deadline)
|
|
69
|
+
return;
|
|
70
|
+
const onTimeout = () => {
|
|
71
|
+
if (this._state === "running") {
|
|
72
|
+
this._state = { error: timeoutError };
|
|
73
|
+
this._forceAbortPromise.reject(timeoutError);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const remaining = deadline - (0, import_utils.monotonicTime)();
|
|
77
|
+
if (remaining <= 0)
|
|
78
|
+
onTimeout();
|
|
79
|
+
else
|
|
80
|
+
timer = setTimeout(onTimeout, remaining);
|
|
81
|
+
};
|
|
66
82
|
const progress = {
|
|
67
83
|
log: (message) => {
|
|
68
84
|
if (this._state === "running")
|
|
69
85
|
this.metadata.log.push(message);
|
|
70
86
|
this.instrumentation.onCallLog(this.sdkObject, this.metadata, this._logName, message);
|
|
71
87
|
},
|
|
72
|
-
timeUntilDeadline: () => this._deadline ? this._deadline - (0, import_utils.monotonicTime)() : 2147483647,
|
|
73
|
-
// 2^31-1 safe setTimeout in Node.
|
|
74
88
|
cleanupWhenAborted: (cleanup) => {
|
|
89
|
+
if (this._strictMode) {
|
|
90
|
+
if (this._state !== "running")
|
|
91
|
+
throw new Error("Internal error: cannot register cleanup after operation has finished.");
|
|
92
|
+
this._cleanups.push(cleanup);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
75
95
|
if (this._state === "running")
|
|
76
96
|
this._cleanups.push(cleanup);
|
|
77
97
|
else
|
|
78
|
-
runCleanup(cleanup);
|
|
79
|
-
},
|
|
80
|
-
throwIfAborted: () => {
|
|
81
|
-
if (typeof this._state === "object")
|
|
82
|
-
throw this._state.error;
|
|
98
|
+
runCleanup(typeof this._state === "object" ? this._state.error : void 0, cleanup);
|
|
83
99
|
},
|
|
84
100
|
metadata: this.metadata,
|
|
85
101
|
race: (promise) => {
|
|
@@ -96,15 +112,19 @@ class ProgressController {
|
|
|
96
112
|
let timer2;
|
|
97
113
|
const promise = new Promise((f) => timer2 = setTimeout(f, timeout2));
|
|
98
114
|
return progress.race(promise).finally(() => clearTimeout(timer2));
|
|
115
|
+
},
|
|
116
|
+
legacyDisableTimeout: () => {
|
|
117
|
+
if (this._strictMode)
|
|
118
|
+
return;
|
|
119
|
+
clearTimeout(timer);
|
|
120
|
+
},
|
|
121
|
+
legacyEnableTimeout: () => {
|
|
122
|
+
if (this._strictMode)
|
|
123
|
+
return;
|
|
124
|
+
startTimer();
|
|
99
125
|
}
|
|
100
126
|
};
|
|
101
|
-
|
|
102
|
-
const timer = setTimeout(() => {
|
|
103
|
-
if (this._state === "running") {
|
|
104
|
-
this._state = { error: timeoutError };
|
|
105
|
-
this._forceAbortPromise.reject(timeoutError);
|
|
106
|
-
}
|
|
107
|
-
}, progress.timeUntilDeadline());
|
|
127
|
+
startTimer();
|
|
108
128
|
try {
|
|
109
129
|
const promise = task(progress);
|
|
110
130
|
const result = this._strictMode ? await promise : await Promise.race([promise, this._forceAbortPromise]);
|
|
@@ -112,7 +132,7 @@ class ProgressController {
|
|
|
112
132
|
return result;
|
|
113
133
|
} catch (error) {
|
|
114
134
|
this._state = { error };
|
|
115
|
-
await Promise.all(this._cleanups.splice(0).map(runCleanup));
|
|
135
|
+
await Promise.all(this._cleanups.splice(0).map((cleanup) => runCleanup(error, cleanup)));
|
|
116
136
|
throw error;
|
|
117
137
|
} finally {
|
|
118
138
|
this.sdkObject.attribution.context?._activeProgressControllers.delete(this);
|
|
@@ -121,9 +141,9 @@ class ProgressController {
|
|
|
121
141
|
}
|
|
122
142
|
}
|
|
123
143
|
}
|
|
124
|
-
async function runCleanup(cleanup) {
|
|
144
|
+
async function runCleanup(error, cleanup) {
|
|
125
145
|
try {
|
|
126
|
-
await cleanup();
|
|
146
|
+
await cleanup(error);
|
|
127
147
|
} catch (e) {
|
|
128
148
|
}
|
|
129
149
|
}
|
|
@@ -127,7 +127,7 @@ class RecorderApp extends import_events.EventEmitter {
|
|
|
127
127
|
timeout: 0
|
|
128
128
|
}
|
|
129
129
|
});
|
|
130
|
-
const controller = new import_progress.ProgressController((0, import_instrumentation.serverSideCallMetadata)(), context._browser
|
|
130
|
+
const controller = new import_progress.ProgressController((0, import_instrumentation.serverSideCallMetadata)(), context._browser);
|
|
131
131
|
await controller.run(async (progress) => {
|
|
132
132
|
await context._browser._defaultContext._loadDefaultContextAsIs(progress);
|
|
133
133
|
});
|
|
@@ -1089,7 +1089,7 @@ ${e.stack}`);
|
|
|
1089
1089
|
async _installMSEdgeChannel(channel, scripts) {
|
|
1090
1090
|
const scriptArgs = [];
|
|
1091
1091
|
if (process.platform !== "linux") {
|
|
1092
|
-
const products = lowercaseAllKeys(JSON.parse(await (0, import_network.fetchData)({ url: "https://edgeupdates.microsoft.com/api/products" })));
|
|
1092
|
+
const products = lowercaseAllKeys(JSON.parse(await (0, import_network.fetchData)(void 0, { url: "https://edgeupdates.microsoft.com/api/products" })));
|
|
1093
1093
|
const productName = {
|
|
1094
1094
|
"msedge": "Stable",
|
|
1095
1095
|
"msedge-beta": "Beta",
|
|
@@ -47,7 +47,7 @@ function downloadFile(options) {
|
|
|
47
47
|
headers: {
|
|
48
48
|
"User-Agent": options.userAgent
|
|
49
49
|
},
|
|
50
|
-
|
|
50
|
+
socketTimeout: options.socketTimeout
|
|
51
51
|
}, (response) => {
|
|
52
52
|
log(`-- response status code: ${response.statusCode}`);
|
|
53
53
|
if (response.statusCode !== 200) {
|
|
@@ -253,7 +253,7 @@ class Screenshotter {
|
|
|
253
253
|
}
|
|
254
254
|
const cleanupHighlight = await this._maskElements(progress, options);
|
|
255
255
|
const quality = format === "jpeg" ? options.quality ?? 80 : void 0;
|
|
256
|
-
const buffer = await
|
|
256
|
+
const buffer = await this._page.delegate.takeScreenshot(progress, format, documentRect, viewportRect, quality, fitsViewport, options.scale || "device");
|
|
257
257
|
await cleanupHighlight();
|
|
258
258
|
if (shouldSetDefaultBackground)
|
|
259
259
|
await progress.race(this._page.delegate.setBackgroundColor());
|
|
@@ -158,7 +158,7 @@ async function openTraceViewerApp(url, browserName, options) {
|
|
|
158
158
|
timeout: 0
|
|
159
159
|
}
|
|
160
160
|
});
|
|
161
|
-
const controller = new import_progress.ProgressController((0, import_instrumentation.serverSideCallMetadata)(), context._browser
|
|
161
|
+
const controller = new import_progress.ProgressController((0, import_instrumentation.serverSideCallMetadata)(), context._browser);
|
|
162
162
|
await controller.run(async (progress) => {
|
|
163
163
|
await context._browser._defaultContext._loadDefaultContextAsIs(progress);
|
|
164
164
|
});
|
package/lib/server/transport.js
CHANGED
|
@@ -43,8 +43,6 @@ class WebSocketTransport {
|
|
|
43
43
|
this._ws = new import_utilsBundle.ws(url, [], {
|
|
44
44
|
maxPayload: 256 * 1024 * 1024,
|
|
45
45
|
// 256Mb,
|
|
46
|
-
// Prevent internal http client error when passing negative timeout.
|
|
47
|
-
handshakeTimeout: Math.max(progress?.timeUntilDeadline() ?? import_utils.DEFAULT_PLAYWRIGHT_TIMEOUT, 1),
|
|
48
46
|
headers: options.headers,
|
|
49
47
|
followRedirects: options.followRedirects,
|
|
50
48
|
agent: /^(https|wss):\/\//.test(url) ? import_happyEyeballs.httpsHappyEyeballsAgent : import_happyEyeballs.httpHappyEyeballsAgent,
|