patchright-core 1.57.0 → 1.58.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ThirdPartyNotices.txt +3223 -308
- package/browsers.json +21 -22
- package/lib/cli/program.js +4 -5
- package/lib/client/api.js +3 -0
- package/lib/client/browser.js +3 -5
- package/lib/client/browserContext.js +40 -4
- package/lib/client/browserType.js +4 -3
- package/lib/client/connection.js +4 -0
- package/lib/client/elementHandle.js +3 -0
- package/lib/client/events.js +3 -0
- package/lib/client/fetch.js +3 -4
- package/lib/client/frame.js +10 -1
- package/lib/client/locator.js +8 -0
- package/lib/client/network.js +5 -1
- package/lib/client/page.js +29 -1
- package/lib/client/pageAgent.js +64 -0
- package/lib/client/platform.js +3 -0
- package/lib/client/tracing.js +1 -1
- package/lib/generated/injectedScriptSource.js +1 -1
- package/lib/generated/pollingRecorderSource.js +1 -1
- package/lib/mcpBundle.js +84 -0
- package/lib/mcpBundleImpl/index.js +147 -0
- package/lib/protocol/serializers.js +5 -0
- package/lib/protocol/validator.js +88 -4
- package/lib/remote/playwrightServer.js +1 -2
- package/lib/server/agent/actionRunner.js +335 -0
- package/lib/server/agent/actions.js +128 -0
- package/lib/server/agent/codegen.js +111 -0
- package/lib/server/agent/context.js +150 -0
- package/lib/server/agent/expectTools.js +156 -0
- package/lib/server/agent/pageAgent.js +204 -0
- package/lib/server/agent/performTools.js +262 -0
- package/lib/server/agent/tool.js +109 -0
- package/lib/server/artifact.js +1 -1
- package/lib/server/bidi/bidiBrowser.js +56 -12
- package/lib/server/bidi/bidiChromium.js +8 -12
- package/lib/server/bidi/bidiConnection.js +1 -0
- package/lib/server/bidi/bidiDeserializer.js +116 -0
- package/lib/server/bidi/bidiExecutionContext.js +75 -29
- package/lib/server/bidi/bidiFirefox.js +6 -8
- package/lib/server/bidi/bidiNetworkManager.js +1 -1
- package/lib/server/bidi/bidiPage.js +39 -28
- package/lib/server/bidi/third_party/bidiProtocolCore.js +1 -0
- package/lib/server/browserContext.js +34 -26
- package/lib/server/browserType.js +12 -4
- package/lib/server/chromium/chromium.js +14 -20
- package/lib/server/chromium/chromiumSwitches.js +2 -2
- package/lib/server/chromium/crBrowser.js +22 -12
- package/lib/server/chromium/crConnection.js +0 -5
- package/lib/server/chromium/crCoverage.js +13 -1
- package/lib/server/chromium/crDevTools.js +0 -2
- package/lib/server/chromium/crNetworkManager.js +92 -12
- package/lib/server/chromium/crPage.js +62 -116
- package/lib/server/codegen/javascript.js +6 -29
- package/lib/server/deviceDescriptorsSource.json +56 -56
- package/lib/server/dispatchers/browserContextDispatcher.js +3 -2
- package/lib/server/dispatchers/dispatcher.js +6 -13
- package/lib/server/dispatchers/frameDispatcher.js +1 -1
- package/lib/server/dispatchers/jsHandleDispatcher.js +2 -2
- package/lib/server/dispatchers/pageAgentDispatcher.js +96 -0
- package/lib/server/dispatchers/pageDispatcher.js +4 -0
- package/lib/server/dom.js +12 -3
- package/lib/server/electron/electron.js +5 -2
- package/lib/server/firefox/ffBrowser.js +10 -20
- package/lib/server/firefox/ffConnection.js +0 -5
- package/lib/server/firefox/ffNetworkManager.js +2 -2
- package/lib/server/firefox/ffPage.js +15 -18
- package/lib/server/firefox/firefox.js +6 -8
- package/lib/server/frameSelectors.js +16 -4
- package/lib/server/frames.js +251 -86
- package/lib/server/instrumentation.js +3 -0
- package/lib/server/javascript.js +8 -4
- package/lib/server/launchApp.js +2 -1
- package/lib/server/network.js +50 -12
- package/lib/server/page.js +61 -91
- package/lib/server/progress.js +26 -6
- package/lib/server/recorder/recorderApp.js +79 -100
- package/lib/server/registry/browserFetcher.js +6 -4
- package/lib/server/registry/index.js +172 -149
- package/lib/server/registry/oopDownloadBrowserMain.js +3 -0
- package/lib/server/screencast.js +190 -0
- package/lib/server/screenshotter.js +6 -0
- package/lib/server/trace/recorder/snapshotter.js +17 -8
- package/lib/server/trace/recorder/snapshotterInjected.js +30 -72
- package/lib/server/trace/recorder/tracing.js +29 -21
- package/lib/server/trace/viewer/traceParser.js +72 -0
- package/lib/server/trace/viewer/traceViewer.js +21 -17
- package/lib/server/utils/expectUtils.js +87 -2
- package/lib/server/utils/hostPlatform.js +15 -0
- package/lib/server/utils/httpServer.js +5 -20
- package/lib/server/utils/network.js +37 -28
- package/lib/server/utils/nodePlatform.js +6 -0
- package/lib/server/{chromium/videoRecorder.js → videoRecorder.js} +22 -13
- package/lib/server/webkit/webkit.js +4 -6
- package/lib/server/webkit/wkBrowser.js +2 -6
- package/lib/server/webkit/wkConnection.js +1 -6
- package/lib/server/webkit/wkInterceptableRequest.js +29 -1
- package/lib/server/webkit/wkPage.js +75 -46
- package/lib/utils/isomorphic/ariaSnapshot.js +60 -2
- package/lib/utils/isomorphic/lruCache.js +51 -0
- package/lib/utils/isomorphic/protocolMetainfo.js +9 -1
- package/lib/utils/isomorphic/stringUtils.js +49 -0
- package/lib/utils/isomorphic/trace/entries.js +16 -0
- package/lib/utils/isomorphic/trace/snapshotRenderer.js +499 -0
- package/lib/utils/isomorphic/trace/snapshotServer.js +120 -0
- package/lib/utils/isomorphic/trace/snapshotStorage.js +89 -0
- package/lib/utils/isomorphic/trace/traceLoader.js +131 -0
- package/lib/utils/isomorphic/trace/traceModel.js +365 -0
- package/lib/utils/isomorphic/trace/traceModernizer.js +400 -0
- package/lib/utils/isomorphic/trace/versions/traceV3.js +16 -0
- package/lib/utils/isomorphic/trace/versions/traceV4.js +16 -0
- package/lib/utils/isomorphic/trace/versions/traceV5.js +16 -0
- package/lib/utils/isomorphic/trace/versions/traceV6.js +16 -0
- package/lib/utils/isomorphic/trace/versions/traceV7.js +16 -0
- package/lib/utils/isomorphic/trace/versions/traceV8.js +16 -0
- package/lib/utils/isomorphic/yaml.js +84 -0
- package/lib/utils.js +2 -0
- package/lib/utilsBundle.js +2 -5
- package/lib/utilsBundleImpl/index.js +165 -165
- package/lib/vite/htmlReport/index.html +21 -21
- package/lib/vite/recorder/assets/codeMirrorModule-CFUTFUO7.js +32 -0
- package/lib/vite/{traceViewer/codeMirrorModule.C3UTv-Ge.css → recorder/assets/codeMirrorModule-DYBRYzYX.css} +1 -1
- package/lib/vite/recorder/assets/{index-Ri0uHF7I.css → index-BSjZa4pk.css} +1 -1
- package/lib/vite/recorder/assets/index-CVkBxsGf.js +193 -0
- package/lib/vite/recorder/index.html +2 -2
- package/lib/vite/traceViewer/assets/codeMirrorModule-BVA4h_ZY.js +32 -0
- package/lib/vite/traceViewer/assets/defaultSettingsView-CjfmcdOz.js +266 -0
- package/lib/vite/{recorder/assets/codeMirrorModule-C3UTv-Ge.css → traceViewer/codeMirrorModule.DYBRYzYX.css} +1 -1
- package/lib/vite/traceViewer/defaultSettingsView.7ch9cixO.css +1 -0
- package/lib/vite/traceViewer/index.BVu7tZDe.css +1 -0
- package/lib/vite/traceViewer/index.BtyWtaE-.js +2 -0
- package/lib/vite/traceViewer/index.html +4 -4
- package/lib/vite/traceViewer/sw.bundle.js +5 -3
- package/lib/vite/traceViewer/uiMode.fyrXARf2.js +5 -0
- package/lib/vite/traceViewer/uiMode.html +3 -3
- package/package.json +2 -1
- package/types/protocol.d.ts +738 -159
- package/types/types.d.ts +25 -38
- package/lib/server/bidi/third_party/bidiDeserializer.js +0 -98
- package/lib/server/trace/test/inMemorySnapshotter.js +0 -87
- package/lib/vite/recorder/assets/codeMirrorModule-CBbSe-ZI.js +0 -25
- package/lib/vite/recorder/assets/index-CpZVd2nA.js +0 -193
- package/lib/vite/traceViewer/assets/codeMirrorModule-DHz0wP2C.js +0 -25
- package/lib/vite/traceViewer/assets/defaultSettingsView-WsZP88O6.js +0 -266
- package/lib/vite/traceViewer/defaultSettingsView.ConWv5KN.css +0 -1
- package/lib/vite/traceViewer/index.C4Y3Aw8n.css +0 -1
- package/lib/vite/traceViewer/index.C8xAeo93.js +0 -2
- package/lib/vite/traceViewer/uiMode.BltraIJB.js +0 -5
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var pageAgentDispatcher_exports = {};
|
|
20
|
+
__export(pageAgentDispatcher_exports, {
|
|
21
|
+
PageAgentDispatcher: () => PageAgentDispatcher
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(pageAgentDispatcher_exports);
|
|
24
|
+
var import_dispatcher = require("./dispatcher");
|
|
25
|
+
var import_pageAgent = require("../agent/pageAgent");
|
|
26
|
+
var import_instrumentation = require("../instrumentation");
|
|
27
|
+
var import_context = require("../agent/context");
|
|
28
|
+
class PageAgentDispatcher extends import_dispatcher.Dispatcher {
|
|
29
|
+
constructor(scope, options) {
|
|
30
|
+
super(scope, new import_instrumentation.SdkObject(scope._object, "pageAgent"), "PageAgent", { page: scope });
|
|
31
|
+
this._type_PageAgent = true;
|
|
32
|
+
this._type_EventTarget = true;
|
|
33
|
+
this._usage = { turns: 0, inputTokens: 0, outputTokens: 0 };
|
|
34
|
+
this._page = scope._object;
|
|
35
|
+
this._context = new import_context.Context(this._page, options, this._eventSupport());
|
|
36
|
+
}
|
|
37
|
+
async perform(params, progress) {
|
|
38
|
+
try {
|
|
39
|
+
await (0, import_pageAgent.pageAgentPerform)(progress, this._context, params.task, params);
|
|
40
|
+
} finally {
|
|
41
|
+
this._context.pushHistory({ type: "perform", description: params.task });
|
|
42
|
+
}
|
|
43
|
+
return { usage: this._usage };
|
|
44
|
+
}
|
|
45
|
+
async expect(params, progress) {
|
|
46
|
+
try {
|
|
47
|
+
await (0, import_pageAgent.pageAgentExpect)(progress, this._context, params.expectation, params);
|
|
48
|
+
} finally {
|
|
49
|
+
this._context.pushHistory({ type: "expect", description: params.expectation });
|
|
50
|
+
}
|
|
51
|
+
return { usage: this._usage };
|
|
52
|
+
}
|
|
53
|
+
async extract(params, progress) {
|
|
54
|
+
const result = await (0, import_pageAgent.pageAgentExtract)(progress, this._context, params.query, params.schema, params);
|
|
55
|
+
return { result, usage: this._usage };
|
|
56
|
+
}
|
|
57
|
+
async usage(params, progress) {
|
|
58
|
+
return { usage: this._usage };
|
|
59
|
+
}
|
|
60
|
+
async dispose(params, progress) {
|
|
61
|
+
progress.metadata.potentiallyClosesScope = true;
|
|
62
|
+
void this.stopPendingOperations(new Error("The agent is disposed"));
|
|
63
|
+
this._dispose();
|
|
64
|
+
}
|
|
65
|
+
_eventSupport() {
|
|
66
|
+
const self = this;
|
|
67
|
+
return {
|
|
68
|
+
onBeforeTurn(params) {
|
|
69
|
+
const userMessage = params.conversation.messages.find((m) => m.role === "user");
|
|
70
|
+
self._dispatchEvent("turn", { role: "user", message: userMessage?.content ?? "" });
|
|
71
|
+
},
|
|
72
|
+
onAfterTurn(params) {
|
|
73
|
+
const usage = { inputTokens: params.totalUsage.input, outputTokens: params.totalUsage.output };
|
|
74
|
+
const intent = params.assistantMessage.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
|
|
75
|
+
self._dispatchEvent("turn", { role: "assistant", message: intent, usage });
|
|
76
|
+
if (!params.assistantMessage.content.filter((c) => c.type === "tool_call").length)
|
|
77
|
+
self._dispatchEvent("turn", { role: "assistant", message: `no tool calls`, usage });
|
|
78
|
+
self._usage = { turns: self._usage.turns + 1, inputTokens: self._usage.inputTokens + usage.inputTokens, outputTokens: self._usage.outputTokens + usage.outputTokens };
|
|
79
|
+
},
|
|
80
|
+
onBeforeToolCall(params) {
|
|
81
|
+
self._dispatchEvent("turn", { role: "assistant", message: `call tool "${params.toolCall.name}"` });
|
|
82
|
+
},
|
|
83
|
+
onAfterToolCall(params) {
|
|
84
|
+
const suffix = params.toolCall.result?.isError ? "failed" : "succeeded";
|
|
85
|
+
self._dispatchEvent("turn", { role: "user", message: `tool "${params.toolCall.name}" ${suffix}` });
|
|
86
|
+
},
|
|
87
|
+
onToolCallError(params) {
|
|
88
|
+
self._dispatchEvent("turn", { role: "user", message: `tool "${params.toolCall.name}" failed: ${params.error.message}` });
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
94
|
+
0 && (module.exports = {
|
|
95
|
+
PageAgentDispatcher
|
|
96
|
+
});
|
|
@@ -36,6 +36,7 @@ var import_networkDispatchers3 = require("./networkDispatchers");
|
|
|
36
36
|
var import_webSocketRouteDispatcher = require("./webSocketRouteDispatcher");
|
|
37
37
|
var import_instrumentation = require("../instrumentation");
|
|
38
38
|
var import_urlMatch = require("../../utils/isomorphic/urlMatch");
|
|
39
|
+
var import_pageAgentDispatcher = require("./pageAgentDispatcher");
|
|
39
40
|
class PageDispatcher extends import_dispatcher.Dispatcher {
|
|
40
41
|
constructor(parentScope, page) {
|
|
41
42
|
const mainFrame = import_frameDispatcher.FrameDispatcher.from(parentScope, page.mainFrame());
|
|
@@ -288,6 +289,9 @@ class PageDispatcher extends import_dispatcher.Dispatcher {
|
|
|
288
289
|
const coverage = this._page.coverage;
|
|
289
290
|
return await coverage.stopCSSCoverage();
|
|
290
291
|
}
|
|
292
|
+
async agent(params, progress) {
|
|
293
|
+
return { agent: new import_pageAgentDispatcher.PageAgentDispatcher(this, params) };
|
|
294
|
+
}
|
|
291
295
|
_onFrameAttached(frame) {
|
|
292
296
|
this._dispatchEvent("frameAttached", { frame: import_frameDispatcher.FrameDispatcher.from(this.parentScope(), frame) });
|
|
293
297
|
}
|
package/lib/server/dom.js
CHANGED
|
@@ -255,6 +255,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
255
255
|
async _retryAction(progress, actionName, action, options) {
|
|
256
256
|
let retry = 0;
|
|
257
257
|
const waitTime = [0, 20, 100, 100, 500];
|
|
258
|
+
const noAutoWaiting = options.__testHookNoAutoWaiting ?? options.noAutoWaiting;
|
|
258
259
|
while (true) {
|
|
259
260
|
if (retry) {
|
|
260
261
|
progress.log(`retrying ${actionName} action${options.trial ? " (trial run)" : ""}`);
|
|
@@ -268,35 +269,43 @@ class ElementHandle extends js.JSHandle {
|
|
|
268
269
|
} else {
|
|
269
270
|
progress.log(`attempting ${actionName} action${options.trial ? " (trial run)" : ""}`);
|
|
270
271
|
}
|
|
271
|
-
if (!options.skipActionPreChecks && !options.force)
|
|
272
|
+
if (!options.skipActionPreChecks && !options.force && !noAutoWaiting)
|
|
272
273
|
await this._frame._page.performActionPreChecks(progress);
|
|
273
274
|
const result = await action(retry);
|
|
274
275
|
++retry;
|
|
275
276
|
if (result === "error:notvisible") {
|
|
276
|
-
if (options.force)
|
|
277
|
+
if (options.force || noAutoWaiting)
|
|
277
278
|
throw new NonRecoverableDOMError("Element is not visible");
|
|
278
279
|
progress.log(" element is not visible");
|
|
279
280
|
continue;
|
|
280
281
|
}
|
|
281
282
|
if (result === "error:notinviewport") {
|
|
282
|
-
if (options.force)
|
|
283
|
+
if (options.force || noAutoWaiting)
|
|
283
284
|
throw new NonRecoverableDOMError("Element is outside of the viewport");
|
|
284
285
|
progress.log(" element is outside of the viewport");
|
|
285
286
|
continue;
|
|
286
287
|
}
|
|
287
288
|
if (result === "error:optionsnotfound") {
|
|
289
|
+
if (noAutoWaiting)
|
|
290
|
+
throw new NonRecoverableDOMError("Did not find some options");
|
|
288
291
|
progress.log(" did not find some options");
|
|
289
292
|
continue;
|
|
290
293
|
}
|
|
291
294
|
if (result === "error:optionnotenabled") {
|
|
295
|
+
if (noAutoWaiting)
|
|
296
|
+
throw new NonRecoverableDOMError("Option being selected is not enabled");
|
|
292
297
|
progress.log(" option being selected is not enabled");
|
|
293
298
|
continue;
|
|
294
299
|
}
|
|
295
300
|
if (typeof result === "object" && "hitTargetDescription" in result) {
|
|
301
|
+
if (noAutoWaiting)
|
|
302
|
+
throw new NonRecoverableDOMError(`${result.hitTargetDescription} intercepts pointer events`);
|
|
296
303
|
progress.log(` ${result.hitTargetDescription} intercepts pointer events`);
|
|
297
304
|
continue;
|
|
298
305
|
}
|
|
299
306
|
if (typeof result === "object" && "missingState" in result) {
|
|
307
|
+
if (noAutoWaiting)
|
|
308
|
+
throw new NonRecoverableDOMError(`Element is not ${result.missingState}`);
|
|
300
309
|
progress.log(` element is not ${result.missingState}`);
|
|
301
310
|
continue;
|
|
302
311
|
}
|
|
@@ -158,8 +158,8 @@ class Electron extends import_instrumentation.SdkObject {
|
|
|
158
158
|
let shell = false;
|
|
159
159
|
if (process.platform === "win32") {
|
|
160
160
|
shell = true;
|
|
161
|
-
command = `"${
|
|
162
|
-
electronArguments =
|
|
161
|
+
command = [command, ...electronArguments].map((arg) => `"${escapeDoubleQuotes(arg)}"`).join(" ");
|
|
162
|
+
electronArguments = [];
|
|
163
163
|
}
|
|
164
164
|
delete env.NODE_OPTIONS;
|
|
165
165
|
const { launchedProcess, gracefullyClose, kill } = await (0, import_processLauncher.launchProcess)({
|
|
@@ -263,6 +263,9 @@ async function waitForLine(progress, process2, regex) {
|
|
|
263
263
|
import_eventsHelper.eventsHelper.removeEventListeners(listeners);
|
|
264
264
|
}
|
|
265
265
|
}
|
|
266
|
+
function escapeDoubleQuotes(str) {
|
|
267
|
+
return str.replace(/"/g, '\\"');
|
|
268
|
+
}
|
|
266
269
|
// Annotate the CommonJS export names for ESM import in node:
|
|
267
270
|
0 && (module.exports = {
|
|
268
271
|
Electron,
|
|
@@ -54,7 +54,6 @@ class FFBrowser extends import_browser.Browser {
|
|
|
54
54
|
this.session.on("Browser.detachedFromTarget", this._onDetachedFromTarget.bind(this));
|
|
55
55
|
this.session.on("Browser.downloadCreated", this._onDownloadCreated.bind(this));
|
|
56
56
|
this.session.on("Browser.downloadFinished", this._onDownloadFinished.bind(this));
|
|
57
|
-
this.session.on("Browser.videoRecordingFinished", this._onVideoRecordingFinished.bind(this));
|
|
58
57
|
}
|
|
59
58
|
static async connect(parent, transport, options) {
|
|
60
59
|
const connection = new import_ffConnection.FFConnection(transport, options.protocolLogger, options.browserLogsCollector);
|
|
@@ -141,12 +140,9 @@ class FFBrowser extends import_browser.Browser {
|
|
|
141
140
|
const error = payload.canceled ? "canceled" : payload.error;
|
|
142
141
|
this._downloadFinished(payload.uuid, error);
|
|
143
142
|
}
|
|
144
|
-
_onVideoRecordingFinished(payload) {
|
|
145
|
-
this._takeVideo(payload.screencastId)?.reportFinished();
|
|
146
|
-
}
|
|
147
143
|
_onDisconnect() {
|
|
148
144
|
for (const video of this._idToVideo.values())
|
|
149
|
-
video.artifact.reportFinished(new import_errors.TargetClosedError());
|
|
145
|
+
video.artifact.reportFinished(new import_errors.TargetClosedError(this.closeReason()));
|
|
150
146
|
this._idToVideo.clear();
|
|
151
147
|
for (const ffPage of this._ffPages.values())
|
|
152
148
|
ffPage.didClose();
|
|
@@ -199,15 +195,13 @@ class FFBrowserContext extends import_browserContext.BrowserContext {
|
|
|
199
195
|
promises.push(this.doUpdateOffline());
|
|
200
196
|
promises.push(this.doUpdateDefaultEmulatedMedia());
|
|
201
197
|
if (this._options.recordVideo) {
|
|
202
|
-
promises.push(this.
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
browserContextId: this._browserContextId
|
|
210
|
-
});
|
|
198
|
+
promises.push(this._browser.session.send("Browser.setScreencastOptions", {
|
|
199
|
+
// validateBrowserContextOptions ensures correct video size.
|
|
200
|
+
options: {
|
|
201
|
+
...this._options.recordVideo.size,
|
|
202
|
+
quality: 90
|
|
203
|
+
},
|
|
204
|
+
browserContextId: this._browserContextId
|
|
211
205
|
}));
|
|
212
206
|
}
|
|
213
207
|
const proxy = this._options.proxyOverride || this._options.proxy;
|
|
@@ -379,12 +373,8 @@ class FFBrowserContext extends import_browserContext.BrowserContext {
|
|
|
379
373
|
}
|
|
380
374
|
async doClose(reason) {
|
|
381
375
|
if (!this._browserContextId) {
|
|
382
|
-
if (this._options.recordVideo)
|
|
383
|
-
await this.
|
|
384
|
-
options: void 0,
|
|
385
|
-
browserContextId: this._browserContextId
|
|
386
|
-
});
|
|
387
|
-
}
|
|
376
|
+
if (this._options.recordVideo)
|
|
377
|
+
await Promise.all(this._ffPages().map((ffPage) => ffPage._page.screencast.stopVideoRecording()));
|
|
388
378
|
await this._browser.close({ reason });
|
|
389
379
|
} else {
|
|
390
380
|
await this._browser.session.send("Browser.removeBrowserContext", { browserContextId: this._browserContextId });
|
|
@@ -90,11 +90,6 @@ class FFSession extends import_events.EventEmitter {
|
|
|
90
90
|
this._connection = connection;
|
|
91
91
|
this._sessionId = sessionId;
|
|
92
92
|
this._rawSend = rawSend;
|
|
93
|
-
this.on = super.on;
|
|
94
|
-
this.addListener = super.addListener;
|
|
95
|
-
this.off = super.removeListener;
|
|
96
|
-
this.removeListener = super.removeListener;
|
|
97
|
-
this.once = super.once;
|
|
98
93
|
}
|
|
99
94
|
markAsCrashed() {
|
|
100
95
|
this._crashed = true;
|
|
@@ -170,9 +170,9 @@ const causeToResourceType = {
|
|
|
170
170
|
TYPE_FONT: "font",
|
|
171
171
|
TYPE_MEDIA: "media",
|
|
172
172
|
TYPE_WEBSOCKET: "websocket",
|
|
173
|
-
TYPE_CSP_REPORT: "
|
|
173
|
+
TYPE_CSP_REPORT: "cspreport",
|
|
174
174
|
TYPE_XSLT: "other",
|
|
175
|
-
TYPE_BEACON: "
|
|
175
|
+
TYPE_BEACON: "beacon",
|
|
176
176
|
TYPE_FETCH: "fetch",
|
|
177
177
|
TYPE_IMAGESET: "image",
|
|
178
178
|
TYPE_WEB_MANIFEST: "manifest"
|
|
@@ -41,9 +41,9 @@ var import_ffConnection = require("./ffConnection");
|
|
|
41
41
|
var import_ffExecutionContext = require("./ffExecutionContext");
|
|
42
42
|
var import_ffInput = require("./ffInput");
|
|
43
43
|
var import_ffNetworkManager = require("./ffNetworkManager");
|
|
44
|
-
var import_debugLogger = require("../utils/debugLogger");
|
|
45
44
|
var import_stackTrace = require("../../utils/isomorphic/stackTrace");
|
|
46
45
|
var import_errors = require("../errors");
|
|
46
|
+
var import_debugLogger = require("../utils/debugLogger");
|
|
47
47
|
const UTILITY_WORLD_NAME = "__playwright_utility_world__";
|
|
48
48
|
class FFPage {
|
|
49
49
|
constructor(session, browserContext, opener) {
|
|
@@ -83,13 +83,16 @@ class FFPage {
|
|
|
83
83
|
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.workerDestroyed", this._onWorkerDestroyed.bind(this)),
|
|
84
84
|
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.dispatchMessageFromWorker", this._onDispatchMessageFromWorker.bind(this)),
|
|
85
85
|
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.crashed", this._onCrashed.bind(this)),
|
|
86
|
-
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.videoRecordingStarted", this._onVideoRecordingStarted.bind(this)),
|
|
87
86
|
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketCreated", this._onWebSocketCreated.bind(this)),
|
|
88
87
|
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketClosed", this._onWebSocketClosed.bind(this)),
|
|
89
88
|
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketFrameReceived", this._onWebSocketFrameReceived.bind(this)),
|
|
90
89
|
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketFrameSent", this._onWebSocketFrameSent.bind(this)),
|
|
91
90
|
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.screencastFrame", this._onScreencastFrame.bind(this))
|
|
92
91
|
];
|
|
92
|
+
const screencast = this._page.screencast;
|
|
93
|
+
const videoOptions = screencast.launchVideoRecorder();
|
|
94
|
+
if (videoOptions)
|
|
95
|
+
screencast.startVideoRecording(videoOptions).catch((e) => import_debugLogger.debugLogger.log("error", e));
|
|
93
96
|
this._session.once("Page.ready", () => {
|
|
94
97
|
if (this._reportedAsNew)
|
|
95
98
|
return;
|
|
@@ -272,11 +275,8 @@ class FFPage {
|
|
|
272
275
|
this._session.markAsCrashed();
|
|
273
276
|
this._page._didCrash();
|
|
274
277
|
}
|
|
275
|
-
_onVideoRecordingStarted(event) {
|
|
276
|
-
this._browserContext._browser._videoStarted(this._browserContext, event.screencastId, event.file, this._page.waitForInitializedOrError());
|
|
277
|
-
}
|
|
278
278
|
didClose() {
|
|
279
|
-
this._markAsError(new import_errors.TargetClosedError());
|
|
279
|
+
this._markAsError(new import_errors.TargetClosedError(this._page.closeReason()));
|
|
280
280
|
this._session.dispose();
|
|
281
281
|
import_eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
|
|
282
282
|
this._networkManager.dispose();
|
|
@@ -417,24 +417,21 @@ class FFPage {
|
|
|
417
417
|
throw e;
|
|
418
418
|
});
|
|
419
419
|
}
|
|
420
|
-
async
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
await this._session.send("Page.stopScreencast");
|
|
426
|
-
}
|
|
420
|
+
async startScreencast(options) {
|
|
421
|
+
await this._session.send("Page.startScreencast", options);
|
|
422
|
+
}
|
|
423
|
+
async stopScreencast() {
|
|
424
|
+
await this._session.sendMayFail("Page.stopScreencast");
|
|
427
425
|
}
|
|
428
426
|
_onScreencastFrame(event) {
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
const screencastId = this._screencastId;
|
|
432
|
-
this._page.throttleScreencastFrameAck(() => {
|
|
433
|
-
this._session.send("Page.screencastFrameAck", { screencastId }).catch((e) => import_debugLogger.debugLogger.log("error", e));
|
|
427
|
+
this._page.screencast.throttleFrameAck(() => {
|
|
428
|
+
this._session.sendMayFail("Page.screencastFrameAck");
|
|
434
429
|
});
|
|
435
430
|
const buffer = Buffer.from(event.data, "base64");
|
|
436
431
|
this._page.emit(import_page2.Page.Events.ScreencastFrame, {
|
|
437
432
|
buffer,
|
|
433
|
+
frameSwapWallTime: event.timestamp * 1e3,
|
|
434
|
+
// timestamp is in seconds, we need to convert to milliseconds.
|
|
438
435
|
width: event.deviceWidth,
|
|
439
436
|
height: event.deviceHeight
|
|
440
437
|
});
|
|
@@ -56,15 +56,13 @@ class Firefox extends import_browserType.BrowserType {
|
|
|
56
56
|
connectToTransport(transport, options) {
|
|
57
57
|
return import_ffBrowser.FFBrowser.connect(this.attribution.playwright, transport, options);
|
|
58
58
|
}
|
|
59
|
-
doRewriteStartupLog(
|
|
60
|
-
if (
|
|
61
|
-
|
|
62
|
-
if (error.logs.includes(`as root in a regular user's session is not supported.`))
|
|
63
|
-
error.logs = "\n" + (0, import_ascii.wrapInASCIIBox)(`Firefox is unable to launch if the $HOME folder isn't owned by the current user.
|
|
59
|
+
doRewriteStartupLog(logs) {
|
|
60
|
+
if (logs.includes(`as root in a regular user's session is not supported.`))
|
|
61
|
+
logs = "\n" + (0, import_ascii.wrapInASCIIBox)(`Firefox is unable to launch if the $HOME folder isn't owned by the current user.
|
|
64
62
|
Workaround: Set the HOME=/root environment variable${process.env.GITHUB_ACTION ? " in your GitHub Actions workflow file" : ""} when running Playwright.`, 1);
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
return
|
|
63
|
+
if (logs.includes("no DISPLAY environment variable specified"))
|
|
64
|
+
logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
|
|
65
|
+
return logs;
|
|
68
66
|
}
|
|
69
67
|
amendEnvironment(env) {
|
|
70
68
|
if (!import_path.default.isAbsolute(import_os.default.homedir()))
|
|
@@ -51,7 +51,9 @@ class FrameSelectors {
|
|
|
51
51
|
if (!resolved)
|
|
52
52
|
throw new Error(`Failed to find frame for selector "${selector}"`);
|
|
53
53
|
return await resolved.injected.evaluateHandle((injected, { info, scope: scope2 }) => {
|
|
54
|
-
|
|
54
|
+
const elements = injected.querySelectorAll(info.parsed, scope2 || document);
|
|
55
|
+
injected.checkDeprecatedSelectorUsage(info.parsed, elements);
|
|
56
|
+
return elements;
|
|
55
57
|
}, { info: resolved.info, scope: resolved.scope });
|
|
56
58
|
}
|
|
57
59
|
async queryCount(selector, options) {
|
|
@@ -60,7 +62,9 @@ class FrameSelectors {
|
|
|
60
62
|
throw new Error(`Failed to find frame for selector "${selector}"`);
|
|
61
63
|
await options.__testHookBeforeQuery?.();
|
|
62
64
|
return await resolved.injected.evaluate((injected, { info }) => {
|
|
63
|
-
|
|
65
|
+
const elements = injected.querySelectorAll(info.parsed, document);
|
|
66
|
+
injected.checkDeprecatedSelectorUsage(info.parsed, elements);
|
|
67
|
+
return elements.length;
|
|
64
68
|
}, { info: resolved.info });
|
|
65
69
|
}
|
|
66
70
|
async queryAll(selector, scope) {
|
|
@@ -68,7 +72,9 @@ class FrameSelectors {
|
|
|
68
72
|
if (!resolved)
|
|
69
73
|
return [];
|
|
70
74
|
const arrayHandle = await resolved.injected.evaluateHandle((injected, { info, scope: scope2 }) => {
|
|
71
|
-
|
|
75
|
+
const elements = injected.querySelectorAll(info.parsed, scope2 || document);
|
|
76
|
+
injected.checkDeprecatedSelectorUsage(info.parsed, elements);
|
|
77
|
+
return elements;
|
|
72
78
|
}, { info: resolved.info, scope: resolved.scope });
|
|
73
79
|
const properties = await arrayHandle.getProperties();
|
|
74
80
|
arrayHandle.dispose();
|
|
@@ -158,6 +164,7 @@ class FrameSelectors {
|
|
|
158
164
|
if (!resolved)
|
|
159
165
|
return;
|
|
160
166
|
const context = await resolved.frame._context(options?.mainWorld ? "main" : resolved.info.world);
|
|
167
|
+
if (!context) throw new Error("Frame was detached");
|
|
161
168
|
const injected = await context.injectedScript();
|
|
162
169
|
return { injected, info: resolved.info, frame: resolved.frame, scope: resolved.scope };
|
|
163
170
|
}
|
|
@@ -287,7 +294,7 @@ class FrameSelectors {
|
|
|
287
294
|
}
|
|
288
295
|
for (const child of queryingElement.children || []) {
|
|
289
296
|
const childrenNodeIndex = queryingElement.children.indexOf(child);
|
|
290
|
-
const childIndex = this._findElementPositionInDomTree(element, child, documentScope, currentIndex + childrenNodeIndex.toString());
|
|
297
|
+
const childIndex = this._findElementPositionInDomTree(element, child, documentScope, currentIndex + "." + childrenNodeIndex.toString());
|
|
291
298
|
if (childIndex !== null) return childIndex;
|
|
292
299
|
}
|
|
293
300
|
if (queryingElement.shadowRoots && Array.isArray(queryingElement.shadowRoots)) {
|
|
@@ -297,6 +304,11 @@ class FrameSelectors {
|
|
|
297
304
|
const childIndex = this._findElementPositionInDomTree(element, shadowRootHandle, documentScope, currentIndex);
|
|
298
305
|
if (childIndex !== null) return childIndex;
|
|
299
306
|
}
|
|
307
|
+
for (const shadowChild of shadowRoot.children || []) {
|
|
308
|
+
const shadowChildIndex = (shadowRoot.children || []).indexOf(shadowChild);
|
|
309
|
+
const childIndex = this._findElementPositionInDomTree(element, shadowChild, documentScope, currentIndex + "." + shadowChildIndex.toString());
|
|
310
|
+
if (childIndex !== null) return childIndex;
|
|
311
|
+
}
|
|
300
312
|
}
|
|
301
313
|
}
|
|
302
314
|
return null;
|