patchright-core 1.48.2 → 1.49.1
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/README.md +2 -2
- package/ThirdPartyNotices.txt +70 -384
- package/bin/reinstall_chrome_beta_linux.sh +10 -8
- package/bin/reinstall_chrome_stable_linux.sh +10 -8
- package/bin/reinstall_msedge_beta_linux.sh +11 -9
- package/bin/reinstall_msedge_dev_linux.sh +11 -9
- package/bin/reinstall_msedge_stable_linux.sh +11 -9
- package/browsers.json +19 -11
- package/lib/cli/program.js +23 -5
- package/lib/client/channelOwner.js +2 -2
- package/lib/client/locator.js +7 -0
- package/lib/client/network.js +5 -0
- package/lib/client/page.js +4 -2
- package/lib/client/tracing.js +13 -0
- package/lib/client/waiter.js +15 -11
- package/lib/generated/consoleApiSource.js +1 -1
- package/lib/generated/injectedScriptSource.js +1 -1
- package/lib/generated/pollingRecorderSource.js +1 -1
- package/lib/generated/webSocketMockSource.js +1 -1
- package/lib/protocol/validator.js +23 -3
- package/lib/server/ariaSnapshot.js +33 -0
- package/lib/server/bidi/bidiChromium.js +1 -1
- package/lib/server/bidi/bidiConnection.js +0 -2
- package/lib/server/bidi/bidiExecutionContext.js +0 -3
- package/lib/server/browserType.js +4 -1
- package/lib/server/chromium/chromium.js +6 -2
- package/lib/server/chromium/crExecutionContext.js +0 -13
- package/lib/server/chromium/crNetworkManager.js +1 -1
- package/lib/server/chromium/crPage.js +4 -5
- package/lib/server/codegen/csharp.js +11 -16
- package/lib/server/codegen/java.js +4 -7
- package/lib/server/codegen/javascript.js +28 -6
- package/lib/server/codegen/python.js +12 -16
- package/lib/server/debugController.js +8 -5
- package/lib/server/deviceDescriptorsSource.json +127 -127
- package/lib/server/dispatchers/androidDispatcher.js +13 -2
- package/lib/server/dispatchers/debugControllerDispatcher.js +1 -1
- package/lib/server/dispatchers/dispatcher.js +1 -1
- package/lib/server/dispatchers/frameDispatcher.js +8 -1
- package/lib/server/dispatchers/tracingDispatcher.js +10 -0
- package/lib/server/dom.js +79 -36
- package/lib/server/fetch.js +30 -17
- package/lib/server/firefox/ffExecutionContext.js +0 -12
- package/lib/server/firefox/ffNetworkManager.js +1 -1
- package/lib/server/frames.js +55 -62
- package/lib/server/index.js +0 -6
- package/lib/server/javascript.js +0 -6
- package/lib/server/page.js +32 -5
- package/lib/server/progress.js +0 -3
- package/lib/server/recorder/recorderApp.js +6 -15
- package/lib/server/recorder/recorderInTraceViewer.js +3 -3
- package/lib/server/recorder/recorderUtils.js +2 -1
- package/lib/server/recorder.js +66 -31
- package/lib/server/registry/index.js +70 -23
- package/lib/server/registry/nativeDeps.js +6 -3
- package/lib/server/socksClientCertificatesInterceptor.js +1 -1
- package/lib/server/trace/recorder/snapshotter.js +1 -12
- package/lib/server/trace/recorder/snapshotterInjected.js +19 -1
- package/lib/server/trace/recorder/tracing.js +69 -15
- package/lib/server/trace/test/inMemorySnapshotter.js +3 -3
- package/lib/server/trace/viewer/traceViewer.js +2 -1
- package/lib/server/webkit/wkBrowser.js +2 -2
- package/lib/server/webkit/wkExecutionContext.js +0 -13
- package/lib/server/webkit/wkPage.js +4 -0
- package/lib/utils/comparators.js +12 -30
- package/lib/utils/crypto.js +1 -4
- package/lib/utils/hostPlatform.js +6 -0
- package/lib/utils/isomorphic/ariaSnapshot.js +267 -0
- package/lib/utils/isomorphic/locatorGenerators.js +23 -5
- package/lib/utils/isomorphic/recorderUtils.js +36 -4
- package/lib/utils/isomorphic/stringUtils.js +30 -0
- package/lib/utils/isomorphic/urlMatch.js +5 -1
- package/lib/utils/network.js +1 -1
- package/lib/utils/sequence.js +64 -0
- package/lib/utils/stackTrace.js +16 -3
- package/lib/utils/zones.js +32 -23
- package/lib/utilsBundle.js +4 -5
- package/lib/utilsBundleImpl/index.js +190 -33
- package/lib/vite/htmlReport/index.html +19 -16
- package/lib/vite/recorder/assets/codeMirrorModule-AFvV6hAs.js +24 -0
- package/lib/vite/recorder/assets/index-_cTWgVuJ.js +184 -0
- package/lib/vite/recorder/assets/{index-BW-aOBcL.css → index-iA1aAGZg.css} +1 -1
- package/lib/vite/recorder/index.html +2 -2
- package/lib/vite/traceViewer/assets/codeMirrorModule-BWCrdKft.js +24 -0
- package/lib/vite/traceViewer/assets/inspectorTab-C_9qyxv5.js +68 -0
- package/lib/vite/traceViewer/assets/workbench-DsQEOQud.js +9 -0
- package/lib/vite/traceViewer/{embedded.BlHoW5LY.js → embedded.D4x_-tXl.js} +1 -1
- package/lib/vite/traceViewer/embedded.html +5 -5
- package/lib/vite/traceViewer/{index.DaWVfou1.js → index.BskMikzx.js} +1 -1
- package/lib/vite/traceViewer/index.html +24 -7
- package/lib/vite/traceViewer/{inspectorTab.DLjBDrQR.css → inspectorTab.DEOUW62d.css} +1 -1
- package/lib/vite/traceViewer/recorder.Dsk1wX5k.js +2 -0
- package/lib/vite/traceViewer/recorder.html +3 -3
- package/lib/vite/traceViewer/sw.bundle.js +3 -3
- package/lib/vite/traceViewer/uiMode.CzKr-TMc.js +5 -0
- package/lib/vite/traceViewer/uiMode.html +6 -6
- package/lib/vite/traceViewer/{uiMode.CAYqod-m.css → uiMode.voC1ZiOQ.css} +1 -1
- package/lib/vite/traceViewer/workbench.C-zR9ysA.css +1 -0
- package/package.json +1 -1
- package/types/protocol.d.ts +58 -10
- package/types/types.d.ts +116 -20
- package/lib/third_party/diff_match_patch.js +0 -2222
- package/lib/vite/recorder/assets/codeMirrorModule-baozm8ur.js +0 -24
- package/lib/vite/recorder/assets/index-2ElAIWFB.js +0 -42
- package/lib/vite/traceViewer/assets/codeMirrorModule-Bh1rfd2w.js +0 -24
- package/lib/vite/traceViewer/assets/inspectorTab-7GHnKvSD.js +0 -64
- package/lib/vite/traceViewer/assets/workbench-DPQnTHYP.js +0 -9
- package/lib/vite/traceViewer/recorder.C4zxcvd2.js +0 -2
- package/lib/vite/traceViewer/uiMode.mTXWniJb.js +0 -5
- package/lib/vite/traceViewer/workbench.D3JVcA9K.css +0 -1
|
@@ -96,8 +96,10 @@ class AndroidDeviceDispatcher extends _dispatcher.Dispatcher {
|
|
|
96
96
|
await this._object.send('swipe', params);
|
|
97
97
|
}
|
|
98
98
|
async info(params) {
|
|
99
|
+
const info = await this._object.send('info', params);
|
|
100
|
+
fixupAndroidElementInfo(info);
|
|
99
101
|
return {
|
|
100
|
-
info
|
|
102
|
+
info
|
|
101
103
|
};
|
|
102
104
|
}
|
|
103
105
|
async inputType(params) {
|
|
@@ -190,4 +192,13 @@ class AndroidSocketDispatcher extends _dispatcher.Dispatcher {
|
|
|
190
192
|
}
|
|
191
193
|
}
|
|
192
194
|
exports.AndroidSocketDispatcher = AndroidSocketDispatcher;
|
|
193
|
-
const keyMap = new Map([['Unknown', 0], ['SoftLeft', 1], ['SoftRight', 2], ['Home', 3], ['Back', 4], ['Call', 5], ['EndCall', 6], ['0', 7], ['1', 8], ['2', 9], ['3', 10], ['4', 11], ['5', 12], ['6', 13], ['7', 14], ['8', 15], ['9', 16], ['Star', 17], ['*', 17], ['Pound', 18], ['#', 18], ['DialUp', 19], ['DialDown', 20], ['DialLeft', 21], ['DialRight', 22], ['DialCenter', 23], ['VolumeUp', 24], ['VolumeDown', 25], ['Power', 26], ['Camera', 27], ['Clear', 28], ['A', 29], ['B', 30], ['C', 31], ['D', 32], ['E', 33], ['F', 34], ['G', 35], ['H', 36], ['I', 37], ['J', 38], ['K', 39], ['L', 40], ['M', 41], ['N', 42], ['O', 43], ['P', 44], ['Q', 45], ['R', 46], ['S', 47], ['T', 48], ['U', 49], ['V', 50], ['W', 51], ['X', 52], ['Y', 53], ['Z', 54], ['Comma', 55], [',', 55], ['Period', 56], ['.', 56], ['AltLeft', 57], ['AltRight', 58], ['ShiftLeft', 59], ['ShiftRight', 60], ['Tab', 61], ['\t', 61], ['Space', 62], [' ', 62], ['Sym', 63], ['Explorer', 64], ['Envelop', 65], ['Enter', 66], ['Del', 67], ['Grave', 68], ['Minus', 69], ['-', 69], ['Equals', 70], ['=', 70], ['LeftBracket', 71], ['(', 71], ['RightBracket', 72], [')', 72], ['Backslash', 73], ['\\', 73], ['Semicolon', 74], [';', 74], ['Apostrophe', 75], ['`', 75], ['Slash', 76], ['/', 76], ['At', 77], ['@', 77], ['Num', 78], ['HeadsetHook', 79], ['Focus', 80], ['Plus', 81], ['Menu', 82], ['Notification', 83], ['Search', 84], ['ChannelUp', 166], ['ChannelDown', 167], ['AppSwitch', 187], ['Assist', 219], ['Cut', 277], ['Copy', 278], ['Paste', 279]]);
|
|
195
|
+
const keyMap = new Map([['Unknown', 0], ['SoftLeft', 1], ['SoftRight', 2], ['Home', 3], ['Back', 4], ['Call', 5], ['EndCall', 6], ['0', 7], ['1', 8], ['2', 9], ['3', 10], ['4', 11], ['5', 12], ['6', 13], ['7', 14], ['8', 15], ['9', 16], ['Star', 17], ['*', 17], ['Pound', 18], ['#', 18], ['DialUp', 19], ['DialDown', 20], ['DialLeft', 21], ['DialRight', 22], ['DialCenter', 23], ['VolumeUp', 24], ['VolumeDown', 25], ['Power', 26], ['Camera', 27], ['Clear', 28], ['A', 29], ['B', 30], ['C', 31], ['D', 32], ['E', 33], ['F', 34], ['G', 35], ['H', 36], ['I', 37], ['J', 38], ['K', 39], ['L', 40], ['M', 41], ['N', 42], ['O', 43], ['P', 44], ['Q', 45], ['R', 46], ['S', 47], ['T', 48], ['U', 49], ['V', 50], ['W', 51], ['X', 52], ['Y', 53], ['Z', 54], ['Comma', 55], [',', 55], ['Period', 56], ['.', 56], ['AltLeft', 57], ['AltRight', 58], ['ShiftLeft', 59], ['ShiftRight', 60], ['Tab', 61], ['\t', 61], ['Space', 62], [' ', 62], ['Sym', 63], ['Explorer', 64], ['Envelop', 65], ['Enter', 66], ['Del', 67], ['Grave', 68], ['Minus', 69], ['-', 69], ['Equals', 70], ['=', 70], ['LeftBracket', 71], ['(', 71], ['RightBracket', 72], [')', 72], ['Backslash', 73], ['\\', 73], ['Semicolon', 74], [';', 74], ['Apostrophe', 75], ['`', 75], ['Slash', 76], ['/', 76], ['At', 77], ['@', 77], ['Num', 78], ['HeadsetHook', 79], ['Focus', 80], ['Plus', 81], ['Menu', 82], ['Notification', 83], ['Search', 84], ['ChannelUp', 166], ['ChannelDown', 167], ['AppSwitch', 187], ['Assist', 219], ['Cut', 277], ['Copy', 278], ['Paste', 279]]);
|
|
196
|
+
function fixupAndroidElementInfo(info) {
|
|
197
|
+
// Some of the properties are nullable, see https://developer.android.com/reference/androidx/test/uiautomator/UiObject2.
|
|
198
|
+
info.clazz = info.clazz || '';
|
|
199
|
+
info.pkg = info.pkg || '';
|
|
200
|
+
info.res = info.res || '';
|
|
201
|
+
info.desc = info.desc || '';
|
|
202
|
+
info.text = info.text || '';
|
|
203
|
+
for (const child of info.children || []) fixupAndroidElementInfo(child);
|
|
204
|
+
}
|
|
@@ -81,7 +81,7 @@ class DebugControllerDispatcher extends _dispatcher.Dispatcher {
|
|
|
81
81
|
await this._object.setRecorderMode(params);
|
|
82
82
|
}
|
|
83
83
|
async highlight(params) {
|
|
84
|
-
await this._object.highlight(params
|
|
84
|
+
await this._object.highlight(params);
|
|
85
85
|
}
|
|
86
86
|
async hideHighlight() {
|
|
87
87
|
await this._object.hideHighlight();
|
|
@@ -384,7 +384,7 @@ class DispatcherConnection {
|
|
|
384
384
|
callMetadata.endTime = (0, _utils.monotonicTime)();
|
|
385
385
|
await (sdkObject === null || sdkObject === void 0 ? void 0 : sdkObject.instrumentation.onAfterCall(sdkObject, callMetadata));
|
|
386
386
|
}
|
|
387
|
-
if (response.error) response.log = callMetadata.log;
|
|
387
|
+
if (response.error) response.log = (0, _utils.compressCallLog)(callMetadata.log);
|
|
388
388
|
this.onmessage(response);
|
|
389
389
|
}
|
|
390
390
|
}
|
|
@@ -10,6 +10,7 @@ var _elementHandlerDispatcher = require("./elementHandlerDispatcher");
|
|
|
10
10
|
var _jsHandleDispatcher = require("./jsHandleDispatcher");
|
|
11
11
|
var _networkDispatchers = require("./networkDispatchers");
|
|
12
12
|
var _utils = require("../../utils");
|
|
13
|
+
var _ariaSnapshot = require("../ariaSnapshot");
|
|
13
14
|
/**
|
|
14
15
|
* Copyright (c) Microsoft Corporation.
|
|
15
16
|
*
|
|
@@ -274,7 +275,8 @@ class FrameDispatcher extends _dispatcher.Dispatcher {
|
|
|
274
275
|
}
|
|
275
276
|
async expect(params, metadata) {
|
|
276
277
|
metadata.potentiallyClosesScope = true;
|
|
277
|
-
|
|
278
|
+
let expectedValue = params.expectedValue ? (0, _jsHandleDispatcher.parseArgument)(params.expectedValue) : undefined;
|
|
279
|
+
if (params.expression === 'to.match.aria' && expectedValue) expectedValue = (0, _ariaSnapshot.parseAriaSnapshot)(expectedValue);
|
|
278
280
|
const result = await this._frame.expect(metadata, params.selector, {
|
|
279
281
|
...params,
|
|
280
282
|
expectedValue
|
|
@@ -282,5 +284,10 @@ class FrameDispatcher extends _dispatcher.Dispatcher {
|
|
|
282
284
|
if (result.received !== undefined) result.received = (0, _jsHandleDispatcher.serializeResult)(result.received);
|
|
283
285
|
return result;
|
|
284
286
|
}
|
|
287
|
+
async ariaSnapshot(params, metadata) {
|
|
288
|
+
return {
|
|
289
|
+
snapshot: await this._frame.ariaSnapshot(metadata, params.selector, params)
|
|
290
|
+
};
|
|
291
|
+
}
|
|
285
292
|
}
|
|
286
293
|
exports.FrameDispatcher = FrameDispatcher;
|
|
@@ -37,6 +37,16 @@ class TracingDispatcher extends _dispatcher.Dispatcher {
|
|
|
37
37
|
async tracingStartChunk(params) {
|
|
38
38
|
return await this._object.startChunk(params);
|
|
39
39
|
}
|
|
40
|
+
async tracingGroup(params, metadata) {
|
|
41
|
+
const {
|
|
42
|
+
name,
|
|
43
|
+
location
|
|
44
|
+
} = params;
|
|
45
|
+
await this._object.group(name, location, metadata);
|
|
46
|
+
}
|
|
47
|
+
async tracingGroupEnd(params) {
|
|
48
|
+
await this._object.groupEnd();
|
|
49
|
+
}
|
|
40
50
|
async tracingStopChunk(params) {
|
|
41
51
|
const {
|
|
42
52
|
artifact,
|
package/lib/server/dom.js
CHANGED
|
@@ -225,17 +225,21 @@ class ElementHandle extends js.JSHandle {
|
|
|
225
225
|
// Allow 1x1 elements. Compensate for rounding errors by comparing with 0.99 instead.
|
|
226
226
|
const filtered = quads.map(quad => intersectQuadWithViewport(quad)).filter(quad => computeQuadArea(quad) > 0.99);
|
|
227
227
|
if (!filtered.length) return 'error:notinviewport';
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
228
|
+
if (this._page._browserContext._browser.options.name === 'firefox') {
|
|
229
|
+
// Firefox internally uses integer coordinates, so 8.x is converted to 8 or 9 when clicking.
|
|
230
|
+
//
|
|
231
|
+
// This does not work nicely for small elements. For example, 1x1 square with corners
|
|
232
|
+
// (8;8) and (9;9) is targeted when clicking at (8;8) but not when clicking at (9;9).
|
|
233
|
+
// So, clicking at (8.x;8.y) will sometimes click at (9;9) and miss the target.
|
|
234
|
+
//
|
|
235
|
+
// Therefore, we try to find an integer point within a quad to make sure we click inside the element.
|
|
236
|
+
for (const quad of filtered) {
|
|
237
|
+
const integerPoint = findIntegerPointInsideQuad(quad);
|
|
238
|
+
if (integerPoint) return integerPoint;
|
|
239
|
+
}
|
|
236
240
|
}
|
|
237
|
-
|
|
238
|
-
return
|
|
241
|
+
// Return the middle point of the first quad.
|
|
242
|
+
return quadMiddlePoint(filtered[0]);
|
|
239
243
|
}
|
|
240
244
|
async _offsetPoint(offset) {
|
|
241
245
|
const [box, border] = await Promise.all([this.boundingBox(), this.evaluateInUtility(([injected, node]) => injected.getElementBorderWidth(node), {}).catch(e => {})]);
|
|
@@ -253,7 +257,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
253
257
|
const waitTime = [0, 20, 100, 100, 500];
|
|
254
258
|
while (progress.isRunning()) {
|
|
255
259
|
if (retry) {
|
|
256
|
-
progress.log(`retrying ${actionName} action${options.trial ? ' (trial run)' : ''}
|
|
260
|
+
progress.log(`retrying ${actionName} action${options.trial ? ' (trial run)' : ''}`);
|
|
257
261
|
const timeout = waitTime[Math.min(retry - 1, waitTime.length - 1)];
|
|
258
262
|
if (timeout) {
|
|
259
263
|
progress.log(` waiting ${timeout}ms`);
|
|
@@ -263,7 +267,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
263
267
|
} else {
|
|
264
268
|
progress.log(`attempting ${actionName} action${options.trial ? ' (trial run)' : ''}`);
|
|
265
269
|
}
|
|
266
|
-
if (!options.
|
|
270
|
+
if (!options.skipActionPreChecks && !options.force) await this._frame._page.performActionPreChecks(progress);
|
|
267
271
|
const result = await action(retry);
|
|
268
272
|
++retry;
|
|
269
273
|
if (result === 'error:notvisible') {
|
|
@@ -294,7 +298,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
294
298
|
}
|
|
295
299
|
async _retryPointerAction(progress, actionName, waitForEnabled, action, options) {
|
|
296
300
|
// Note: do not perform locator handlers checkpoint to avoid moving the mouse in the middle of a drag operation.
|
|
297
|
-
const
|
|
301
|
+
const skipActionPreChecks = actionName === 'move and up';
|
|
298
302
|
return await this._retryAction(progress, actionName, async retry => {
|
|
299
303
|
// By default, we scroll with protocol method to reveal the action point.
|
|
300
304
|
// However, that might not work to scroll from under position:sticky elements
|
|
@@ -314,7 +318,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
314
318
|
return await this._performPointerAction(progress, actionName, waitForEnabled, action, forceScrollOptions, options);
|
|
315
319
|
}, {
|
|
316
320
|
...options,
|
|
317
|
-
|
|
321
|
+
skipActionPreChecks
|
|
318
322
|
});
|
|
319
323
|
}
|
|
320
324
|
async _performPointerAction(progress, actionName, waitForEnabled, action, forceScrollOptions, options) {
|
|
@@ -367,7 +371,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
367
371
|
if (typeof maybePoint === 'string') return maybePoint;
|
|
368
372
|
const point = roundPoint(maybePoint);
|
|
369
373
|
progress.metadata.point = point;
|
|
370
|
-
await
|
|
374
|
+
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
|
|
371
375
|
let hitTargetInterceptionHandle;
|
|
372
376
|
if (force) {
|
|
373
377
|
progress.log(` forcing action`);
|
|
@@ -433,9 +437,16 @@ class ElementHandle extends js.JSHandle {
|
|
|
433
437
|
progress.log(' navigations have finished');
|
|
434
438
|
return 'done';
|
|
435
439
|
}
|
|
440
|
+
async _markAsTargetElement(metadata) {
|
|
441
|
+
if (!metadata.id) return;
|
|
442
|
+
await this.evaluateInUtility(([injected, node, callId]) => {
|
|
443
|
+
if (node.nodeType === 1 /* Node.ELEMENT_NODE */) injected.markTargetElements(new Set([node]), callId);
|
|
444
|
+
}, metadata.id);
|
|
445
|
+
}
|
|
436
446
|
async hover(metadata, options) {
|
|
437
447
|
const controller = new _progress.ProgressController(metadata, this);
|
|
438
448
|
return controller.run(async progress => {
|
|
449
|
+
await this._markAsTargetElement(metadata);
|
|
439
450
|
const result = await this._hover(progress, options);
|
|
440
451
|
return assertDone(throwRetargetableDOMError(result));
|
|
441
452
|
}, this._page._timeoutSettings.timeout(options));
|
|
@@ -449,6 +460,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
449
460
|
async click(metadata, options = {}) {
|
|
450
461
|
const controller = new _progress.ProgressController(metadata, this);
|
|
451
462
|
return controller.run(async progress => {
|
|
463
|
+
await this._markAsTargetElement(metadata);
|
|
452
464
|
const result = await this._click(progress, {
|
|
453
465
|
...options,
|
|
454
466
|
waitAfter: !options.noWaitAfter
|
|
@@ -462,6 +474,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
462
474
|
async dblclick(metadata, options) {
|
|
463
475
|
const controller = new _progress.ProgressController(metadata, this);
|
|
464
476
|
return controller.run(async progress => {
|
|
477
|
+
await this._markAsTargetElement(metadata);
|
|
465
478
|
const result = await this._dblclick(progress, options);
|
|
466
479
|
return assertDone(throwRetargetableDOMError(result));
|
|
467
480
|
}, this._page._timeoutSettings.timeout(options));
|
|
@@ -475,6 +488,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
475
488
|
async tap(metadata, options = {}) {
|
|
476
489
|
const controller = new _progress.ProgressController(metadata, this);
|
|
477
490
|
return controller.run(async progress => {
|
|
491
|
+
await this._markAsTargetElement(metadata);
|
|
478
492
|
const result = await this._tap(progress, options);
|
|
479
493
|
return assertDone(throwRetargetableDOMError(result));
|
|
480
494
|
}, this._page._timeoutSettings.timeout(options));
|
|
@@ -488,6 +502,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
488
502
|
async selectOption(metadata, elements, values, options) {
|
|
489
503
|
const controller = new _progress.ProgressController(metadata, this);
|
|
490
504
|
return controller.run(async progress => {
|
|
505
|
+
await this._markAsTargetElement(metadata);
|
|
491
506
|
const result = await this._selectOption(progress, elements, values, options);
|
|
492
507
|
return throwRetargetableDOMError(result);
|
|
493
508
|
}, this._page._timeoutSettings.timeout(options));
|
|
@@ -495,7 +510,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
495
510
|
async _selectOption(progress, elements, values, options) {
|
|
496
511
|
let resultingOptions = [];
|
|
497
512
|
await this._retryAction(progress, 'select option', async () => {
|
|
498
|
-
await
|
|
513
|
+
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
|
|
499
514
|
if (!options.force) progress.log(` waiting for element to be visible and enabled`);
|
|
500
515
|
const optionsToSelect = [...elements, ...values];
|
|
501
516
|
const result = await this.evaluateInUtility(async ([injected, node, {
|
|
@@ -523,6 +538,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
523
538
|
async fill(metadata, value, options = {}) {
|
|
524
539
|
const controller = new _progress.ProgressController(metadata, this);
|
|
525
540
|
return controller.run(async progress => {
|
|
541
|
+
await this._markAsTargetElement(metadata);
|
|
526
542
|
const result = await this._fill(progress, value, options);
|
|
527
543
|
assertDone(throwRetargetableDOMError(result));
|
|
528
544
|
}, this._page._timeoutSettings.timeout(options));
|
|
@@ -530,7 +546,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
530
546
|
async _fill(progress, value, options) {
|
|
531
547
|
progress.log(` fill("${value}")`);
|
|
532
548
|
return await this._retryAction(progress, 'fill', async () => {
|
|
533
|
-
await
|
|
549
|
+
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
|
|
534
550
|
if (!options.force) progress.log(' waiting for element to be visible, enabled and editable');
|
|
535
551
|
const result = await this.evaluateInUtility(async ([injected, node, {
|
|
536
552
|
value,
|
|
@@ -578,6 +594,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
578
594
|
const inputFileItems = await (0, _fileUploadUtils.prepareFilesForUpload)(this._frame, params);
|
|
579
595
|
const controller = new _progress.ProgressController(metadata, this);
|
|
580
596
|
return controller.run(async progress => {
|
|
597
|
+
await this._markAsTargetElement(metadata);
|
|
581
598
|
const result = await this._setInputFiles(progress, inputFileItems);
|
|
582
599
|
return assertDone(throwRetargetableDOMError(result));
|
|
583
600
|
}, this._page._timeoutSettings.timeout(params));
|
|
@@ -607,7 +624,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
607
624
|
});
|
|
608
625
|
if (result === 'error:notconnected' || !result.asElement()) return 'error:notconnected';
|
|
609
626
|
const retargeted = result.asElement();
|
|
610
|
-
await
|
|
627
|
+
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
|
|
611
628
|
progress.throwIfAborted(); // Avoid action that has side-effects.
|
|
612
629
|
if (localPaths || localDirectory) {
|
|
613
630
|
const localPathsOrDirectory = localDirectory ? [localDirectory] : localPaths;
|
|
@@ -628,6 +645,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
628
645
|
async focus(metadata) {
|
|
629
646
|
const controller = new _progress.ProgressController(metadata, this);
|
|
630
647
|
await controller.run(async progress => {
|
|
648
|
+
await this._markAsTargetElement(metadata);
|
|
631
649
|
const result = await this._focus(progress);
|
|
632
650
|
return assertDone(throwRetargetableDOMError(result));
|
|
633
651
|
}, 0);
|
|
@@ -643,13 +661,14 @@ class ElementHandle extends js.JSHandle {
|
|
|
643
661
|
async type(metadata, text, options) {
|
|
644
662
|
const controller = new _progress.ProgressController(metadata, this);
|
|
645
663
|
return controller.run(async progress => {
|
|
664
|
+
await this._markAsTargetElement(metadata);
|
|
646
665
|
const result = await this._type(progress, text, options);
|
|
647
666
|
return assertDone(throwRetargetableDOMError(result));
|
|
648
667
|
}, this._page._timeoutSettings.timeout(options));
|
|
649
668
|
}
|
|
650
669
|
async _type(progress, text, options) {
|
|
651
670
|
progress.log(`elementHandle.type("${text}")`);
|
|
652
|
-
await
|
|
671
|
+
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
|
|
653
672
|
const result = await this._focus(progress, true /* resetSelectionIfNotFocused */);
|
|
654
673
|
if (result !== 'done') return result;
|
|
655
674
|
progress.throwIfAborted(); // Avoid action that has side-effects.
|
|
@@ -659,13 +678,14 @@ class ElementHandle extends js.JSHandle {
|
|
|
659
678
|
async press(metadata, key, options) {
|
|
660
679
|
const controller = new _progress.ProgressController(metadata, this);
|
|
661
680
|
return controller.run(async progress => {
|
|
681
|
+
await this._markAsTargetElement(metadata);
|
|
662
682
|
const result = await this._press(progress, key, options);
|
|
663
683
|
return assertDone(throwRetargetableDOMError(result));
|
|
664
684
|
}, this._page._timeoutSettings.timeout(options));
|
|
665
685
|
}
|
|
666
686
|
async _press(progress, key, options) {
|
|
667
687
|
progress.log(`elementHandle.press("${key}")`);
|
|
668
|
-
await
|
|
688
|
+
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
|
|
669
689
|
return this._page._frameManager.waitForSignalsCreatedBy(progress, !options.noWaitAfter, async () => {
|
|
670
690
|
const result = await this._focus(progress, true /* resetSelectionIfNotFocused */);
|
|
671
691
|
if (result !== 'done') return result;
|
|
@@ -693,6 +713,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
693
713
|
const result = await this.evaluateInUtility(([injected, node]) => injected.elementState(node, 'checked'), {});
|
|
694
714
|
return throwRetargetableDOMError(result);
|
|
695
715
|
};
|
|
716
|
+
await this._markAsTargetElement(progress.metadata);
|
|
696
717
|
if ((await isChecked()) === state) return 'done';
|
|
697
718
|
const result = await this._click(progress, {
|
|
698
719
|
...options,
|
|
@@ -706,6 +727,9 @@ class ElementHandle extends js.JSHandle {
|
|
|
706
727
|
async boundingBox() {
|
|
707
728
|
return this._page._delegate.getBoundingBox(this);
|
|
708
729
|
}
|
|
730
|
+
async ariaSnapshot() {
|
|
731
|
+
return await this.evaluateInUtility(([injected, element]) => injected.ariaSnapshot(element), {});
|
|
732
|
+
}
|
|
709
733
|
async screenshot(metadata, options = {}) {
|
|
710
734
|
const controller = new _progress.ProgressController(metadata, this);
|
|
711
735
|
return controller.run(progress => this._page._screenshotter.screenshotElement(progress, this, options), this._page._timeoutSettings.timeout(options));
|
|
@@ -825,21 +849,40 @@ function roundPoint(point) {
|
|
|
825
849
|
y: (point.y * 100 | 0) / 100
|
|
826
850
|
};
|
|
827
851
|
}
|
|
828
|
-
function
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
852
|
+
function quadMiddlePoint(quad) {
|
|
853
|
+
const result = {
|
|
854
|
+
x: 0,
|
|
855
|
+
y: 0
|
|
856
|
+
};
|
|
857
|
+
for (const point of quad) {
|
|
858
|
+
result.x += point.x / 4;
|
|
859
|
+
result.y += point.y / 4;
|
|
860
|
+
}
|
|
861
|
+
return result;
|
|
862
|
+
}
|
|
863
|
+
function triangleArea(p1, p2, p3) {
|
|
864
|
+
return Math.abs(p1.x * (p2.y - p3.y) + p2.x * (p3.y - p1.y) + p3.x * (p1.y - p2.y)) / 2;
|
|
865
|
+
}
|
|
866
|
+
function isPointInsideQuad(point, quad) {
|
|
867
|
+
const area1 = triangleArea(point, quad[0], quad[1]) + triangleArea(point, quad[1], quad[2]) + triangleArea(point, quad[2], quad[3]) + triangleArea(point, quad[3], quad[0]);
|
|
868
|
+
const area2 = triangleArea(quad[0], quad[1], quad[2]) + triangleArea(quad[1], quad[2], quad[3]);
|
|
869
|
+
// Check that point is inside the quad.
|
|
870
|
+
if (Math.abs(area1 - area2) > 0.1) return false;
|
|
871
|
+
// Check that point is not on the right/bottom edge, because clicking
|
|
872
|
+
// there does not actually click the element.
|
|
873
|
+
return point.x < Math.max(quad[0].x, quad[1].x, quad[2].x, quad[3].x) && point.y < Math.max(quad[0].y, quad[1].y, quad[2].y, quad[3].y);
|
|
874
|
+
}
|
|
875
|
+
function findIntegerPointInsideQuad(quad) {
|
|
876
|
+
// Try all four rounding directions of the middle point.
|
|
877
|
+
const point = quadMiddlePoint(quad);
|
|
878
|
+
point.x = Math.floor(point.x);
|
|
879
|
+
point.y = Math.floor(point.y);
|
|
880
|
+
if (isPointInsideQuad(point, quad)) return point;
|
|
881
|
+
point.x += 1;
|
|
882
|
+
if (isPointInsideQuad(point, quad)) return point;
|
|
883
|
+
point.y += 1;
|
|
884
|
+
if (isPointInsideQuad(point, quad)) return point;
|
|
885
|
+
point.x -= 1;
|
|
886
|
+
if (isPointInsideQuad(point, quad)) return point;
|
|
844
887
|
}
|
|
845
888
|
const kUnableToAdoptErrorMessage = exports.kUnableToAdoptErrorMessage = 'Unable to adopt element handle from a different document';
|
package/lib/server/fetch.js
CHANGED
|
@@ -8,7 +8,6 @@ exports.createProxyAgent = createProxyAgent;
|
|
|
8
8
|
var _http = _interopRequireDefault(require("http"));
|
|
9
9
|
var _https = _interopRequireDefault(require("https"));
|
|
10
10
|
var _stream = require("stream");
|
|
11
|
-
var _url = _interopRequireDefault(require("url"));
|
|
12
11
|
var _zlib = _interopRequireDefault(require("zlib"));
|
|
13
12
|
var _timeoutSettings = require("../common/timeoutSettings");
|
|
14
13
|
var _userAgent = require("../utils/userAgent");
|
|
@@ -91,7 +90,7 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
91
90
|
value
|
|
92
91
|
} of params.headers) setHeader(headers, name, value);
|
|
93
92
|
}
|
|
94
|
-
const requestUrl = new URL(
|
|
93
|
+
const requestUrl = new URL((0, _utils.constructURLBasedOnBaseURL)(defaults.baseURL, params.url));
|
|
95
94
|
if (params.encodedParams) {
|
|
96
95
|
requestUrl.search = params.encodedParams;
|
|
97
96
|
} else if (params.params) {
|
|
@@ -218,6 +217,7 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
218
217
|
agent
|
|
219
218
|
};
|
|
220
219
|
const startAt = (0, _utils.monotonicTime)();
|
|
220
|
+
let reusedSocketAt;
|
|
221
221
|
let dnsLookupAt;
|
|
222
222
|
let tcpConnectionAt;
|
|
223
223
|
let tlsHandshakeAt;
|
|
@@ -232,15 +232,16 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
232
232
|
var _tlsHandshakeAt;
|
|
233
233
|
const endAt = (0, _utils.monotonicTime)();
|
|
234
234
|
// spec: http://www.softwareishard.com/blog/har-12-spec/#timings
|
|
235
|
+
const connectEnd = (_tlsHandshakeAt = tlsHandshakeAt) !== null && _tlsHandshakeAt !== void 0 ? _tlsHandshakeAt : tcpConnectionAt;
|
|
235
236
|
const timings = {
|
|
236
237
|
send: requestFinishAt - startAt,
|
|
237
238
|
wait: responseAt - requestFinishAt,
|
|
238
239
|
receive: endAt - responseAt,
|
|
239
240
|
dns: dnsLookupAt ? dnsLookupAt - startAt : -1,
|
|
240
|
-
connect:
|
|
241
|
+
connect: connectEnd ? connectEnd - startAt : -1,
|
|
241
242
|
// "If [ssl] is defined then the time is also included in the connect field "
|
|
242
243
|
ssl: tlsHandshakeAt ? tlsHandshakeAt - tcpConnectionAt : -1,
|
|
243
|
-
blocked: -1
|
|
244
|
+
blocked: reusedSocketAt ? reusedSocketAt - startAt : -1
|
|
244
245
|
};
|
|
245
246
|
const requestFinishedEvent = {
|
|
246
247
|
requestEvent,
|
|
@@ -387,16 +388,23 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
387
388
|
}));
|
|
388
389
|
request.on('close', () => _utils.eventsHelper.removeEventListeners(listeners));
|
|
389
390
|
request.on('socket', socket => {
|
|
391
|
+
var _tcpConnectionAt, _tcpConnectionAt3;
|
|
392
|
+
if (request.reusedSocket) {
|
|
393
|
+
reusedSocketAt = (0, _utils.monotonicTime)();
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
|
|
390
397
|
// happy eyeballs don't emit lookup and connect events, so we use our custom ones
|
|
391
398
|
const happyEyeBallsTimings = (0, _happyEyeballs.timingForSocket)(socket);
|
|
392
399
|
dnsLookupAt = happyEyeBallsTimings.dnsLookupAt;
|
|
393
|
-
tcpConnectionAt = happyEyeBallsTimings.tcpConnectionAt;
|
|
400
|
+
(_tcpConnectionAt = tcpConnectionAt) !== null && _tcpConnectionAt !== void 0 ? _tcpConnectionAt : tcpConnectionAt = happyEyeBallsTimings.tcpConnectionAt;
|
|
394
401
|
|
|
395
402
|
// non-happy-eyeballs sockets
|
|
396
403
|
listeners.push(_utils.eventsHelper.addEventListener(socket, 'lookup', () => {
|
|
397
404
|
dnsLookupAt = (0, _utils.monotonicTime)();
|
|
398
405
|
}), _utils.eventsHelper.addEventListener(socket, 'connect', () => {
|
|
399
|
-
|
|
406
|
+
var _tcpConnectionAt2;
|
|
407
|
+
(_tcpConnectionAt2 = tcpConnectionAt) !== null && _tcpConnectionAt2 !== void 0 ? _tcpConnectionAt2 : tcpConnectionAt = (0, _utils.monotonicTime)();
|
|
400
408
|
}), _utils.eventsHelper.addEventListener(socket, 'secureConnect', () => {
|
|
401
409
|
tlsHandshakeAt = (0, _utils.monotonicTime)();
|
|
402
410
|
if (socket instanceof _tls.TLSSocket) {
|
|
@@ -411,12 +419,21 @@ class APIRequestContext extends _instrumentation.SdkObject {
|
|
|
411
419
|
};
|
|
412
420
|
}
|
|
413
421
|
}));
|
|
422
|
+
|
|
423
|
+
// when using socks proxy, having the socket means the connection got established
|
|
424
|
+
if (agent instanceof _utilsBundle.SocksProxyAgent) (_tcpConnectionAt3 = tcpConnectionAt) !== null && _tcpConnectionAt3 !== void 0 ? _tcpConnectionAt3 : tcpConnectionAt = (0, _utils.monotonicTime)();
|
|
414
425
|
serverIPAddress = socket.remoteAddress;
|
|
415
426
|
serverPort = socket.remotePort;
|
|
416
427
|
});
|
|
417
428
|
request.on('finish', () => {
|
|
418
429
|
requestFinishAt = (0, _utils.monotonicTime)();
|
|
419
430
|
});
|
|
431
|
+
|
|
432
|
+
// http proxy
|
|
433
|
+
request.on('proxyConnect', () => {
|
|
434
|
+
var _tcpConnectionAt4;
|
|
435
|
+
(_tcpConnectionAt4 = tcpConnectionAt) !== null && _tcpConnectionAt4 !== void 0 ? _tcpConnectionAt4 : tcpConnectionAt = (0, _utils.monotonicTime)();
|
|
436
|
+
});
|
|
420
437
|
progress.log(`→ ${options.method} ${url.toString()}`);
|
|
421
438
|
if (options.headers) {
|
|
422
439
|
for (const [name, value] of Object.entries(options.headers)) progress.log(` ${name}: ${value}`);
|
|
@@ -562,17 +579,13 @@ class GlobalAPIRequestContext extends APIRequestContext {
|
|
|
562
579
|
}
|
|
563
580
|
exports.GlobalAPIRequestContext = GlobalAPIRequestContext;
|
|
564
581
|
function createProxyAgent(proxy) {
|
|
565
|
-
var
|
|
566
|
-
const
|
|
567
|
-
if ((
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
}
|
|
573
|
-
if (proxy.username) proxyOpts.auth = `${proxy.username}:${proxy.password || ''}`;
|
|
574
|
-
// TODO: We should use HttpProxyAgent conditional on proxyOpts.protocol instead of always using CONNECT method.
|
|
575
|
-
return new _utilsBundle.HttpsProxyAgent(proxyOpts);
|
|
582
|
+
var _proxyURL$protocol;
|
|
583
|
+
const proxyURL = new URL(proxy.server);
|
|
584
|
+
if ((_proxyURL$protocol = proxyURL.protocol) !== null && _proxyURL$protocol !== void 0 && _proxyURL$protocol.startsWith('socks')) return new _utilsBundle.SocksProxyAgent(proxyURL);
|
|
585
|
+
if (proxy.username) proxyURL.username = proxy.username;
|
|
586
|
+
if (proxy.password) proxyURL.password = proxy.password;
|
|
587
|
+
// TODO: We should use HttpProxyAgent conditional on proxyURL.protocol instead of always using CONNECT method.
|
|
588
|
+
return new _utilsBundle.HttpsProxyAgent(proxyURL);
|
|
576
589
|
}
|
|
577
590
|
function toHeadersArray(rawHeaders) {
|
|
578
591
|
const result = [];
|
|
@@ -52,18 +52,6 @@ class FFExecutionContext {
|
|
|
52
52
|
checkException(payload.exceptionDetails);
|
|
53
53
|
return payload.result.objectId;
|
|
54
54
|
}
|
|
55
|
-
rawCallFunctionNoReply(func, ...args) {
|
|
56
|
-
this._session.send('Runtime.callFunction', {
|
|
57
|
-
functionDeclaration: func.toString(),
|
|
58
|
-
args: args.map(a => a instanceof js.JSHandle ? {
|
|
59
|
-
objectId: a._objectId
|
|
60
|
-
} : {
|
|
61
|
-
value: a
|
|
62
|
-
}),
|
|
63
|
-
returnByValue: true,
|
|
64
|
-
executionContextId: this._executionContextId
|
|
65
|
-
}).catch(() => {});
|
|
66
|
-
}
|
|
67
55
|
async evaluateWithArguments(expression, returnByValue, utilityScript, values, objectIds) {
|
|
68
56
|
const payload = await this._session.send('Runtime.callFunction', {
|
|
69
57
|
functionDeclaration: expression,
|