Update npm packages (73 packages including @jqhtml 2.3.36)
Update npm registry domain from privatenpm.hanson.xyz to npm.internal.hanson.xyz 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2923
node_modules/playwright-core/ThirdPartyNotices.txt
generated
vendored
2923
node_modules/playwright-core/ThirdPartyNotices.txt
generated
vendored
File diff suppressed because it is too large
Load Diff
43
node_modules/playwright-core/browsers.json
generated
vendored
43
node_modules/playwright-core/browsers.json
generated
vendored
@@ -3,59 +3,58 @@
|
||||
"browsers": [
|
||||
{
|
||||
"name": "chromium",
|
||||
"revision": "1200",
|
||||
"revision": "1208",
|
||||
"installByDefault": true,
|
||||
"browserVersion": "143.0.7499.4"
|
||||
"browserVersion": "145.0.7632.6",
|
||||
"title": "Chrome for Testing"
|
||||
},
|
||||
{
|
||||
"name": "chromium-headless-shell",
|
||||
"revision": "1200",
|
||||
"revision": "1208",
|
||||
"installByDefault": true,
|
||||
"browserVersion": "143.0.7499.4"
|
||||
"browserVersion": "145.0.7632.6",
|
||||
"title": "Chrome Headless Shell"
|
||||
},
|
||||
{
|
||||
"name": "chromium-tip-of-tree",
|
||||
"revision": "1380",
|
||||
"revision": "1401",
|
||||
"installByDefault": false,
|
||||
"browserVersion": "143.0.7488.0"
|
||||
"browserVersion": "146.0.7644.0",
|
||||
"title": "Chrome Canary for Testing"
|
||||
},
|
||||
{
|
||||
"name": "chromium-tip-of-tree-headless-shell",
|
||||
"revision": "1380",
|
||||
"revision": "1401",
|
||||
"installByDefault": false,
|
||||
"browserVersion": "143.0.7488.0"
|
||||
"browserVersion": "146.0.7644.0",
|
||||
"title": "Chrome Canary Headless Shell"
|
||||
},
|
||||
{
|
||||
"name": "firefox",
|
||||
"revision": "1497",
|
||||
"revision": "1509",
|
||||
"installByDefault": true,
|
||||
"browserVersion": "144.0.2"
|
||||
"browserVersion": "146.0.1",
|
||||
"title": "Firefox"
|
||||
},
|
||||
{
|
||||
"name": "firefox-beta",
|
||||
"revision": "1493",
|
||||
"revision": "1504",
|
||||
"installByDefault": false,
|
||||
"browserVersion": "145.0b10"
|
||||
"browserVersion": "146.0b8",
|
||||
"title": "Firefox Beta"
|
||||
},
|
||||
{
|
||||
"name": "webkit",
|
||||
"revision": "2227",
|
||||
"revision": "2248",
|
||||
"installByDefault": true,
|
||||
"revisionOverrides": {
|
||||
"debian11-x64": "2105",
|
||||
"debian11-arm64": "2105",
|
||||
"mac10.14": "1446",
|
||||
"mac10.15": "1616",
|
||||
"mac11": "1816",
|
||||
"mac11-arm64": "1816",
|
||||
"mac12": "2009",
|
||||
"mac12-arm64": "2009",
|
||||
"mac13": "2140",
|
||||
"mac13-arm64": "2140",
|
||||
"ubuntu20.04-x64": "2092",
|
||||
"ubuntu20.04-arm64": "2092"
|
||||
},
|
||||
"browserVersion": "26.0"
|
||||
"browserVersion": "26.0",
|
||||
"title": "WebKit"
|
||||
},
|
||||
{
|
||||
"name": "ffmpeg",
|
||||
|
||||
9
node_modules/playwright-core/lib/cli/program.js
generated
vendored
9
node_modules/playwright-core/lib/cli/program.js
generated
vendored
@@ -124,7 +124,7 @@ Playwright version: ${version}`);
|
||||
printInstalledBrowsers(groupedByPlaywrightMinorVersion.get(version));
|
||||
}
|
||||
}
|
||||
import_utilsBundle.program.command("install [browser...]").description("ensure browsers necessary for this version of Playwright are installed").option("--with-deps", "install system dependencies for browsers").option("--dry-run", "do not execute installation, only print information").option("--list", "prints list of browsers from all playwright installations").option("--force", "force reinstall of stable browser channels").option("--only-shell", "only install headless shell when installing chromium").option("--no-shell", "do not install chromium headless shell").action(async function(args, options) {
|
||||
import_utilsBundle.program.command("install [browser...]").description("ensure browsers necessary for this version of Playwright are installed").option("--with-deps", "install system dependencies for browsers").option("--dry-run", "do not execute installation, only print information").option("--list", "prints list of browsers from all playwright installations").option("--force", "force reinstall of already installed browsers").option("--only-shell", "only install headless shell when installing chromium").option("--no-shell", "do not install chromium headless shell").action(async function(args, options) {
|
||||
if ((0, import_utils.isLikelyNpxGlobal)()) {
|
||||
console.error((0, import_ascii.wrapInASCIIBox)([
|
||||
`WARNING: It looks like you are running 'npx playwright install' without first`,
|
||||
@@ -156,8 +156,7 @@ import_utilsBundle.program.command("install [browser...]").description("ensure b
|
||||
throw new Error(`Only one of --dry-run and --list can be specified`);
|
||||
if (options.dryRun) {
|
||||
for (const executable of executables) {
|
||||
const version = executable.browserVersion ? `version ` + executable.browserVersion : "";
|
||||
console.log(`browser: ${executable.name}${version ? " " + version : ""}`);
|
||||
console.log(import_server.registry.calculateDownloadTitle(executable));
|
||||
console.log(` Install location: ${executable.directory ?? "<system>"}`);
|
||||
if (executable.downloadURLs?.length) {
|
||||
const [url, ...fallbacks] = executable.downloadURLs;
|
||||
@@ -171,8 +170,7 @@ import_utilsBundle.program.command("install [browser...]").description("ensure b
|
||||
const browsers2 = await import_server.registry.listInstalledBrowsers();
|
||||
printGroupedByPlaywrightVersion(browsers2);
|
||||
} else {
|
||||
const force = args.length === 0 ? false : !!options.force;
|
||||
await import_server.registry.install(executables, { force });
|
||||
await import_server.registry.install(executables, { force: options.force });
|
||||
await import_server.registry.validateHostRequirementsForExecutablesIfNeeded(executables, process.env.PW_LANG_NAME || "javascript").catch((e) => {
|
||||
e.name = "Playwright Host validation warning";
|
||||
console.error(e);
|
||||
@@ -423,6 +421,7 @@ async function openPage(context, url) {
|
||||
}
|
||||
async function open(options, url) {
|
||||
const { context } = await launchContext(options, { headless: !!process.env.PWTEST_CLI_HEADLESS, executablePath: process.env.PWTEST_CLI_EXECUTABLE_PATH });
|
||||
await context._exposeConsoleApi();
|
||||
await openPage(context, url);
|
||||
}
|
||||
async function codegen(options, url) {
|
||||
|
||||
3
node_modules/playwright-core/lib/client/api.js
generated
vendored
3
node_modules/playwright-core/lib/client/api.js
generated
vendored
@@ -46,6 +46,7 @@ __export(api_exports, {
|
||||
Locator: () => import_locator.Locator,
|
||||
Mouse: () => import_input.Mouse,
|
||||
Page: () => import_page.Page,
|
||||
PageAgent: () => import_pageAgent.PageAgent,
|
||||
Playwright: () => import_playwright.Playwright,
|
||||
Request: () => import_network.Request,
|
||||
Response: () => import_network.Response,
|
||||
@@ -81,6 +82,7 @@ var import_jsHandle = require("./jsHandle");
|
||||
var import_network = require("./network");
|
||||
var import_fetch = require("./fetch");
|
||||
var import_page = require("./page");
|
||||
var import_pageAgent = require("./pageAgent");
|
||||
var import_selectors = require("./selectors");
|
||||
var import_tracing = require("./tracing");
|
||||
var import_video = require("./video");
|
||||
@@ -118,6 +120,7 @@ var import_webError = require("./webError");
|
||||
Locator,
|
||||
Mouse,
|
||||
Page,
|
||||
PageAgent,
|
||||
Playwright,
|
||||
Request,
|
||||
Response,
|
||||
|
||||
8
node_modules/playwright-core/lib/client/browser.js
generated
vendored
8
node_modules/playwright-core/lib/client/browser.js
generated
vendored
@@ -62,11 +62,9 @@ class Browser extends import_channelOwner.ChannelOwner {
|
||||
context._onClose();
|
||||
await this._channel.disconnectFromReusedContext({ reason });
|
||||
}
|
||||
async _innerNewContext(options = {}, forReuse) {
|
||||
options = this._browserType._playwright.selectors._withSelectorOptions({
|
||||
...this._browserType._playwright._defaultContextOptions,
|
||||
...options
|
||||
});
|
||||
async _innerNewContext(userOptions = {}, forReuse) {
|
||||
const options = this._browserType._playwright.selectors._withSelectorOptions(userOptions);
|
||||
await this._instrumentation.runBeforeCreateBrowserContext(options);
|
||||
const contextOptions = await (0, import_browserContext.prepareBrowserContextParams)(this._platform, options);
|
||||
const response = forReuse ? await this._channel.newContextForReuse(contextOptions) : await this._channel.newContext(contextOptions);
|
||||
const context = import_browserContext.BrowserContext.from(response.context);
|
||||
|
||||
35
node_modules/playwright-core/lib/client/browserContext.js
generated
vendored
35
node_modules/playwright-core/lib/client/browserContext.js
generated
vendored
@@ -76,6 +76,7 @@ class BrowserContext extends import_channelOwner.ChannelOwner {
|
||||
this.tracing = import_tracing.Tracing.from(initializer.tracing);
|
||||
this.request = import_fetch.APIRequestContext.from(initializer.requestContext);
|
||||
this.request._timeoutSettings = this._timeoutSettings;
|
||||
this.request._checkUrlAllowed = (url) => this._checkUrlAllowed(url);
|
||||
this.clock = new import_clock.Clock(this);
|
||||
this._channel.on("bindingCall", ({ binding }) => this._onBinding(import_page.BindingCall.from(binding)));
|
||||
this._channel.on("close", () => this._onClose());
|
||||
@@ -474,6 +475,40 @@ class BrowserContext extends import_channelOwner.ChannelOwner {
|
||||
this._onRecorderEventSink = void 0;
|
||||
await this._channel.disableRecorder();
|
||||
}
|
||||
async _exposeConsoleApi() {
|
||||
await this._channel.exposeConsoleApi();
|
||||
}
|
||||
_setAllowedProtocols(protocols) {
|
||||
this._allowedProtocols = protocols;
|
||||
}
|
||||
_checkUrlAllowed(url) {
|
||||
if (!this._allowedProtocols)
|
||||
return;
|
||||
let parsedURL;
|
||||
try {
|
||||
parsedURL = new URL(url);
|
||||
} catch (e) {
|
||||
throw new Error(`Access to ${url} is blocked. Invalid URL: ${e.message}`);
|
||||
}
|
||||
if (!this._allowedProtocols.includes(parsedURL.protocol))
|
||||
throw new Error(`Access to "${parsedURL.protocol}" URL is blocked. Allowed protocols: ${this._allowedProtocols.join(", ")}. Attempted URL: ${url}`);
|
||||
}
|
||||
_setAllowedDirectories(rootDirectories) {
|
||||
this._allowedDirectories = rootDirectories;
|
||||
}
|
||||
_checkFileAccess(filePath) {
|
||||
if (!this._allowedDirectories)
|
||||
return;
|
||||
const path = this._platform.path().resolve(filePath);
|
||||
const isInsideDir = (container, child) => {
|
||||
const path2 = this._platform.path();
|
||||
const rel = path2.relative(container, child);
|
||||
return !!rel && !rel.startsWith("..") && !path2.isAbsolute(rel);
|
||||
};
|
||||
if (this._allowedDirectories.some((root) => isInsideDir(root, path)))
|
||||
return;
|
||||
throw new Error(`File access denied: ${filePath} is outside allowed roots. Allowed roots: ${this._allowedDirectories.length ? this._allowedDirectories.join(", ") : "none"}`);
|
||||
}
|
||||
}
|
||||
async function prepareStorageState(platform, storageState) {
|
||||
if (typeof storageState !== "string")
|
||||
|
||||
7
node_modules/playwright-core/lib/client/browserType.js
generated
vendored
7
node_modules/playwright-core/lib/client/browserType.js
generated
vendored
@@ -73,13 +73,13 @@ class BrowserType extends import_channelOwner.ChannelOwner {
|
||||
return await this._serverLauncher.launchServer(options);
|
||||
}
|
||||
async launchPersistentContext(userDataDir, options = {}) {
|
||||
const logger = options.logger || this._playwright._defaultLaunchOptions?.logger;
|
||||
(0, import_assert.assert)(!options.port, "Cannot specify a port without launching as a server.");
|
||||
options = this._playwright.selectors._withSelectorOptions({
|
||||
...this._playwright._defaultLaunchOptions,
|
||||
...this._playwright._defaultContextOptions,
|
||||
...options
|
||||
});
|
||||
await this._instrumentation.runBeforeCreateBrowserContext(options);
|
||||
const logger = options.logger || this._playwright._defaultLaunchOptions?.logger;
|
||||
const contextParams = await (0, import_browserContext.prepareBrowserContextParams)(this._platform, options);
|
||||
const persistentParams = {
|
||||
...contextParams,
|
||||
@@ -169,7 +169,8 @@ class BrowserType extends import_channelOwner.ChannelOwner {
|
||||
endpointURL,
|
||||
headers,
|
||||
slowMo: params.slowMo,
|
||||
timeout: new import_timeoutSettings.TimeoutSettings(this._platform).timeout(params)
|
||||
timeout: new import_timeoutSettings.TimeoutSettings(this._platform).timeout(params),
|
||||
isLocal: params.isLocal
|
||||
});
|
||||
const browser = import_browser.Browser.from(result.browser);
|
||||
browser._connectToBrowserType(this, {}, params.logger);
|
||||
|
||||
4
node_modules/playwright-core/lib/client/connection.js
generated
vendored
4
node_modules/playwright-core/lib/client/connection.js
generated
vendored
@@ -48,6 +48,7 @@ var import_worker = require("./worker");
|
||||
var import_writableStream = require("./writableStream");
|
||||
var import_validator = require("../protocol/validator");
|
||||
var import_stackTrace = require("../utils/isomorphic/stackTrace");
|
||||
var import_pageAgent = require("./pageAgent");
|
||||
class Root extends import_channelOwner.ChannelOwner {
|
||||
constructor(connection) {
|
||||
super(connection, "Root", "", {});
|
||||
@@ -261,6 +262,9 @@ class Connection extends import_eventEmitter.EventEmitter {
|
||||
case "Page":
|
||||
result = new import_page.Page(parent, type, guid, initializer);
|
||||
break;
|
||||
case "PageAgent":
|
||||
result = new import_pageAgent.PageAgent(parent, type, guid, initializer);
|
||||
break;
|
||||
case "Playwright":
|
||||
result = new import_playwright.Playwright(parent, type, guid, initializer);
|
||||
break;
|
||||
|
||||
3
node_modules/playwright-core/lib/client/elementHandle.js
generated
vendored
3
node_modules/playwright-core/lib/client/elementHandle.js
generated
vendored
@@ -230,6 +230,9 @@ async function convertInputFiles(platform, files, context) {
|
||||
if (!items.every((item) => typeof item === "string"))
|
||||
throw new Error("File paths cannot be mixed with buffers");
|
||||
const [localPaths, localDirectory] = await resolvePathsAndDirectoryForInputFiles(platform, items);
|
||||
localPaths?.forEach((path) => context._checkFileAccess(path));
|
||||
if (localDirectory)
|
||||
context._checkFileAccess(localDirectory);
|
||||
if (context._connection.isRemote()) {
|
||||
const files2 = localDirectory ? (await platform.fs().promises.readdir(localDirectory, { withFileTypes: true, recursive: true })).filter((f) => f.isFile()).map((f) => platform.path().join(f.path, f.name)) : localPaths;
|
||||
const { writableStreams, rootDir } = await context._wrapApiCall(async () => context._channel.createTempFiles({
|
||||
|
||||
3
node_modules/playwright-core/lib/client/events.js
generated
vendored
3
node_modules/playwright-core/lib/client/events.js
generated
vendored
@@ -78,6 +78,9 @@ const Events = {
|
||||
WebSocket: "websocket",
|
||||
Worker: "worker"
|
||||
},
|
||||
PageAgent: {
|
||||
Turn: "turn"
|
||||
},
|
||||
WebSocket: {
|
||||
Close: "close",
|
||||
Error: "socketerror",
|
||||
|
||||
7
node_modules/playwright-core/lib/client/fetch.js
generated
vendored
7
node_modules/playwright-core/lib/client/fetch.js
generated
vendored
@@ -39,10 +39,8 @@ class APIRequest {
|
||||
this._playwright = playwright;
|
||||
}
|
||||
async newContext(options = {}) {
|
||||
options = {
|
||||
...this._playwright._defaultContextOptions,
|
||||
...options
|
||||
};
|
||||
options = { ...options };
|
||||
await this._playwright._instrumentation.runBeforeCreateRequestContext(options);
|
||||
const storageState = typeof options.storageState === "string" ? JSON.parse(await this._playwright._platform.fs().promises.readFile(options.storageState, "utf8")) : options.storageState;
|
||||
const context = APIRequestContext.from((await this._playwright._channel.newRequest({
|
||||
...options,
|
||||
@@ -135,6 +133,7 @@ class APIRequestContext extends import_channelOwner.ChannelOwner {
|
||||
(0, import_assert.assert)(options.maxRedirects === void 0 || options.maxRedirects >= 0, `'maxRedirects' must be greater than or equal to '0'`);
|
||||
(0, import_assert.assert)(options.maxRetries === void 0 || options.maxRetries >= 0, `'maxRetries' must be greater than or equal to '0'`);
|
||||
const url = options.url !== void 0 ? options.url : options.request.url();
|
||||
this._checkUrlAllowed?.(url);
|
||||
const method = options.method || options.request?.method();
|
||||
let encodedParams = void 0;
|
||||
if (typeof options.params === "string")
|
||||
|
||||
1
node_modules/playwright-core/lib/client/frame.js
generated
vendored
1
node_modules/playwright-core/lib/client/frame.js
generated
vendored
@@ -101,6 +101,7 @@ class Frame extends import_channelOwner.ChannelOwner {
|
||||
}
|
||||
async goto(url, options = {}) {
|
||||
const waitUntil = verifyLoadState("waitUntil", options.waitUntil === void 0 ? "load" : options.waitUntil);
|
||||
this.page().context()._checkUrlAllowed(url);
|
||||
return network.Response.fromNullable((await this._channel.goto({ url, ...options, waitUntil, timeout: this._navigationTimeout(options) })).response);
|
||||
}
|
||||
_setupNavigationWaiter(options) {
|
||||
|
||||
29
node_modules/playwright-core/lib/client/page.js
generated
vendored
29
node_modules/playwright-core/lib/client/page.js
generated
vendored
@@ -48,6 +48,7 @@ var import_urlMatch = require("../utils/isomorphic/urlMatch");
|
||||
var import_manualPromise = require("../utils/isomorphic/manualPromise");
|
||||
var import_rtti = require("../utils/isomorphic/rtti");
|
||||
var import_consoleMessage = require("./consoleMessage");
|
||||
var import_pageAgent = require("./pageAgent");
|
||||
class Page extends import_channelOwner.ChannelOwner {
|
||||
constructor(parent, type, guid, initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
@@ -62,6 +63,7 @@ class Page extends import_channelOwner.ChannelOwner {
|
||||
this._closeWasCalled = false;
|
||||
this._harRouters = [];
|
||||
this._locatorHandlers = /* @__PURE__ */ new Map();
|
||||
this._instrumentation.onPage(this);
|
||||
this._browserContext = parent;
|
||||
this._timeoutSettings = new import_timeoutSettings.TimeoutSettings(this._platform, this._browserContext._timeoutSettings);
|
||||
this.keyboard = new import_input.Keyboard(this);
|
||||
@@ -502,7 +504,8 @@ class Page extends import_channelOwner.ChannelOwner {
|
||||
}
|
||||
async close(options = {}) {
|
||||
this._closeReason = options.reason;
|
||||
this._closeWasCalled = true;
|
||||
if (!options.runBeforeUnload)
|
||||
this._closeWasCalled = true;
|
||||
try {
|
||||
if (this._ownedContext)
|
||||
await this._ownedContext.close();
|
||||
@@ -673,6 +676,30 @@ class Page extends import_channelOwner.ChannelOwner {
|
||||
}
|
||||
return result.pdf;
|
||||
}
|
||||
// @ts-expect-error agents are hidden
|
||||
async agent(options = {}) {
|
||||
const params = {
|
||||
api: options.provider?.api,
|
||||
apiEndpoint: options.provider?.apiEndpoint,
|
||||
apiKey: options.provider?.apiKey,
|
||||
apiTimeout: options.provider?.apiTimeout,
|
||||
apiCacheFile: options.provider?._apiCacheFile,
|
||||
doNotRenderActive: options._doNotRenderActive,
|
||||
model: options.provider?.model,
|
||||
cacheFile: options.cache?.cacheFile,
|
||||
cacheOutFile: options.cache?.cacheOutFile,
|
||||
maxTokens: options.limits?.maxTokens,
|
||||
maxActions: options.limits?.maxActions,
|
||||
maxActionRetries: options.limits?.maxActionRetries,
|
||||
// @ts-expect-error runAgents is hidden
|
||||
secrets: options.secrets ? Object.entries(options.secrets).map(([name, value]) => ({ name, value })) : void 0,
|
||||
systemPrompt: options.systemPrompt
|
||||
};
|
||||
const { agent } = await this._channel.agent(params);
|
||||
const pageAgent = import_pageAgent.PageAgent.from(agent);
|
||||
pageAgent._expectTimeout = options?.expect?.timeout;
|
||||
return pageAgent;
|
||||
}
|
||||
async _snapshotForAI(options = {}) {
|
||||
return await this._channel.snapshotForAI({ timeout: this._timeoutSettings.timeout(options), track: options.track });
|
||||
}
|
||||
|
||||
64
node_modules/playwright-core/lib/client/pageAgent.js
generated
vendored
Normal file
64
node_modules/playwright-core/lib/client/pageAgent.js
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var pageAgent_exports = {};
|
||||
__export(pageAgent_exports, {
|
||||
PageAgent: () => PageAgent
|
||||
});
|
||||
module.exports = __toCommonJS(pageAgent_exports);
|
||||
var import_channelOwner = require("./channelOwner");
|
||||
var import_events = require("./events");
|
||||
var import_page = require("./page");
|
||||
class PageAgent extends import_channelOwner.ChannelOwner {
|
||||
static from(channel) {
|
||||
return channel._object;
|
||||
}
|
||||
constructor(parent, type, guid, initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
this._page = import_page.Page.from(initializer.page);
|
||||
this._channel.on("turn", (params) => this.emit(import_events.Events.PageAgent.Turn, params));
|
||||
}
|
||||
async expect(expectation, options = {}) {
|
||||
const timeout = options.timeout ?? this._expectTimeout ?? 5e3;
|
||||
await this._channel.expect({ expectation, ...options, timeout });
|
||||
}
|
||||
async perform(task, options = {}) {
|
||||
const timeout = this._page._timeoutSettings.timeout(options);
|
||||
const { usage } = await this._channel.perform({ task, ...options, timeout });
|
||||
return { usage };
|
||||
}
|
||||
async extract(query, schema, options = {}) {
|
||||
const timeout = this._page._timeoutSettings.timeout(options);
|
||||
const { result, usage } = await this._channel.extract({ query, schema: this._page._platform.zodToJsonSchema(schema), ...options, timeout });
|
||||
return { result, usage };
|
||||
}
|
||||
async usage() {
|
||||
const { usage } = await this._channel.usage({});
|
||||
return usage;
|
||||
}
|
||||
async dispose() {
|
||||
await this._channel.dispose();
|
||||
}
|
||||
async [Symbol.asyncDispose]() {
|
||||
await this.dispose();
|
||||
}
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
PageAgent
|
||||
});
|
||||
3
node_modules/playwright-core/lib/client/platform.js
generated
vendored
3
node_modules/playwright-core/lib/client/platform.js
generated
vendored
@@ -66,6 +66,9 @@ const emptyPlatform = {
|
||||
streamWritable: (channel) => {
|
||||
throw new Error("Streams are not available");
|
||||
},
|
||||
zodToJsonSchema: (schema) => {
|
||||
throw new Error("Zod is not available");
|
||||
},
|
||||
zones: { empty: noopZone, current: () => noopZone }
|
||||
};
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
|
||||
2
node_modules/playwright-core/lib/generated/injectedScriptSource.js
generated
vendored
2
node_modules/playwright-core/lib/generated/injectedScriptSource.js
generated
vendored
File diff suppressed because one or more lines are too long
2
node_modules/playwright-core/lib/generated/pollingRecorderSource.js
generated
vendored
2
node_modules/playwright-core/lib/generated/pollingRecorderSource.js
generated
vendored
File diff suppressed because one or more lines are too long
84
node_modules/playwright-core/lib/mcpBundle.js
generated
vendored
Executable file
84
node_modules/playwright-core/lib/mcpBundle.js
generated
vendored
Executable file
@@ -0,0 +1,84 @@
|
||||
"use strict";
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||
// If the importer is in node compatibility mode or this is not an ESM
|
||||
// file that has been converted to a CommonJS file using a Babel-
|
||||
// compatible transform (i.e. "__esModule" has not been set), then set
|
||||
// "default" to the CommonJS "module.exports" for node compatibility.
|
||||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||
mod
|
||||
));
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var mcpBundle_exports = {};
|
||||
__export(mcpBundle_exports, {
|
||||
CallToolRequestSchema: () => CallToolRequestSchema,
|
||||
Client: () => Client,
|
||||
ListRootsRequestSchema: () => ListRootsRequestSchema,
|
||||
ListToolsRequestSchema: () => ListToolsRequestSchema,
|
||||
Loop: () => Loop,
|
||||
PingRequestSchema: () => PingRequestSchema,
|
||||
ProgressNotificationSchema: () => ProgressNotificationSchema,
|
||||
SSEClientTransport: () => SSEClientTransport,
|
||||
SSEServerTransport: () => SSEServerTransport,
|
||||
Server: () => Server,
|
||||
StdioClientTransport: () => StdioClientTransport,
|
||||
StdioServerTransport: () => StdioServerTransport,
|
||||
StreamableHTTPClientTransport: () => StreamableHTTPClientTransport,
|
||||
StreamableHTTPServerTransport: () => StreamableHTTPServerTransport,
|
||||
z: () => z,
|
||||
zodToJsonSchema: () => zodToJsonSchema
|
||||
});
|
||||
module.exports = __toCommonJS(mcpBundle_exports);
|
||||
var bundle = __toESM(require("./mcpBundleImpl"));
|
||||
const zodToJsonSchema = bundle.zodToJsonSchema;
|
||||
const Client = bundle.Client;
|
||||
const Server = bundle.Server;
|
||||
const SSEClientTransport = bundle.SSEClientTransport;
|
||||
const SSEServerTransport = bundle.SSEServerTransport;
|
||||
const StdioClientTransport = bundle.StdioClientTransport;
|
||||
const StdioServerTransport = bundle.StdioServerTransport;
|
||||
const StreamableHTTPServerTransport = bundle.StreamableHTTPServerTransport;
|
||||
const StreamableHTTPClientTransport = bundle.StreamableHTTPClientTransport;
|
||||
const CallToolRequestSchema = bundle.CallToolRequestSchema;
|
||||
const ListRootsRequestSchema = bundle.ListRootsRequestSchema;
|
||||
const ProgressNotificationSchema = bundle.ProgressNotificationSchema;
|
||||
const ListToolsRequestSchema = bundle.ListToolsRequestSchema;
|
||||
const PingRequestSchema = bundle.PingRequestSchema;
|
||||
const Loop = bundle.Loop;
|
||||
const z = bundle.z;
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
CallToolRequestSchema,
|
||||
Client,
|
||||
ListRootsRequestSchema,
|
||||
ListToolsRequestSchema,
|
||||
Loop,
|
||||
PingRequestSchema,
|
||||
ProgressNotificationSchema,
|
||||
SSEClientTransport,
|
||||
SSEServerTransport,
|
||||
Server,
|
||||
StdioClientTransport,
|
||||
StdioServerTransport,
|
||||
StreamableHTTPClientTransport,
|
||||
StreamableHTTPServerTransport,
|
||||
z,
|
||||
zodToJsonSchema
|
||||
});
|
||||
147
node_modules/playwright-core/lib/mcpBundleImpl/index.js
generated
vendored
Normal file
147
node_modules/playwright-core/lib/mcpBundleImpl/index.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
5
node_modules/playwright-core/lib/protocol/serializers.js
generated
vendored
5
node_modules/playwright-core/lib/protocol/serializers.js
generated
vendored
@@ -19,6 +19,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
||||
var serializers_exports = {};
|
||||
__export(serializers_exports, {
|
||||
parseSerializedValue: () => parseSerializedValue,
|
||||
serializePlainValue: () => serializePlainValue,
|
||||
serializeValue: () => serializeValue
|
||||
});
|
||||
module.exports = __toCommonJS(serializers_exports);
|
||||
@@ -90,6 +91,9 @@ function innerParseSerializedValue(value, handles, refs, accessChain) {
|
||||
function serializeValue(value, handleSerializer) {
|
||||
return innerSerializeValue(value, handleSerializer, { lastId: 0, visited: /* @__PURE__ */ new Map() }, []);
|
||||
}
|
||||
function serializePlainValue(arg) {
|
||||
return serializeValue(arg, (value) => ({ fallThrough: value }));
|
||||
}
|
||||
function innerSerializeValue(value, handleSerializer, visitorInfo, accessChain) {
|
||||
const handle = handleSerializer(value);
|
||||
if ("fallThrough" in handle)
|
||||
@@ -188,5 +192,6 @@ const constructorToTypedArrayKind = new Map(Object.entries(typedArrayKindToConst
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
parseSerializedValue,
|
||||
serializePlainValue,
|
||||
serializeValue
|
||||
});
|
||||
|
||||
85
node_modules/playwright-core/lib/protocol/validator.js
generated
vendored
85
node_modules/playwright-core/lib/protocol/validator.js
generated
vendored
@@ -512,7 +512,6 @@ import_validatorPrimitives.scheme.BrowserTypeLaunchParams = (0, import_validator
|
||||
timeout: import_validatorPrimitives.tFloat,
|
||||
env: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue"))),
|
||||
headless: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tBoolean),
|
||||
devtools: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tBoolean),
|
||||
proxy: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
||||
server: import_validatorPrimitives.tString,
|
||||
bypass: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
||||
@@ -542,7 +541,6 @@ import_validatorPrimitives.scheme.BrowserTypeLaunchPersistentContextParams = (0,
|
||||
timeout: import_validatorPrimitives.tFloat,
|
||||
env: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue"))),
|
||||
headless: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tBoolean),
|
||||
devtools: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tBoolean),
|
||||
proxy: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
||||
server: import_validatorPrimitives.tString,
|
||||
bypass: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
||||
@@ -621,7 +619,8 @@ import_validatorPrimitives.scheme.BrowserTypeConnectOverCDPParams = (0, import_v
|
||||
endpointURL: import_validatorPrimitives.tString,
|
||||
headers: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue"))),
|
||||
slowMo: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tFloat),
|
||||
timeout: import_validatorPrimitives.tFloat
|
||||
timeout: import_validatorPrimitives.tFloat,
|
||||
isLocal: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tBoolean)
|
||||
});
|
||||
import_validatorPrimitives.scheme.BrowserTypeConnectOverCDPResult = (0, import_validatorPrimitives.tObject)({
|
||||
browser: (0, import_validatorPrimitives.tChannel)(["Browser"]),
|
||||
@@ -821,6 +820,7 @@ import_validatorPrimitives.scheme.WorkerWaitForEventInfoParams = (0, import_vali
|
||||
import_validatorPrimitives.scheme.WebSocketWaitForEventInfoParams = (0, import_validatorPrimitives.tType)("EventTargetWaitForEventInfoParams");
|
||||
import_validatorPrimitives.scheme.ElectronApplicationWaitForEventInfoParams = (0, import_validatorPrimitives.tType)("EventTargetWaitForEventInfoParams");
|
||||
import_validatorPrimitives.scheme.AndroidDeviceWaitForEventInfoParams = (0, import_validatorPrimitives.tType)("EventTargetWaitForEventInfoParams");
|
||||
import_validatorPrimitives.scheme.PageAgentWaitForEventInfoParams = (0, import_validatorPrimitives.tType)("EventTargetWaitForEventInfoParams");
|
||||
import_validatorPrimitives.scheme.EventTargetWaitForEventInfoResult = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
||||
import_validatorPrimitives.scheme.BrowserContextWaitForEventInfoResult = (0, import_validatorPrimitives.tType)("EventTargetWaitForEventInfoResult");
|
||||
import_validatorPrimitives.scheme.PageWaitForEventInfoResult = (0, import_validatorPrimitives.tType)("EventTargetWaitForEventInfoResult");
|
||||
@@ -828,6 +828,7 @@ import_validatorPrimitives.scheme.WorkerWaitForEventInfoResult = (0, import_vali
|
||||
import_validatorPrimitives.scheme.WebSocketWaitForEventInfoResult = (0, import_validatorPrimitives.tType)("EventTargetWaitForEventInfoResult");
|
||||
import_validatorPrimitives.scheme.ElectronApplicationWaitForEventInfoResult = (0, import_validatorPrimitives.tType)("EventTargetWaitForEventInfoResult");
|
||||
import_validatorPrimitives.scheme.AndroidDeviceWaitForEventInfoResult = (0, import_validatorPrimitives.tType)("EventTargetWaitForEventInfoResult");
|
||||
import_validatorPrimitives.scheme.PageAgentWaitForEventInfoResult = (0, import_validatorPrimitives.tType)("EventTargetWaitForEventInfoResult");
|
||||
import_validatorPrimitives.scheme.BrowserContextInitializer = (0, import_validatorPrimitives.tObject)({
|
||||
isChromium: import_validatorPrimitives.tBoolean,
|
||||
requestContext: (0, import_validatorPrimitives.tChannel)(["APIRequestContext"]),
|
||||
@@ -1075,6 +1076,8 @@ import_validatorPrimitives.scheme.BrowserContextEnableRecorderParams = (0, impor
|
||||
import_validatorPrimitives.scheme.BrowserContextEnableRecorderResult = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
||||
import_validatorPrimitives.scheme.BrowserContextDisableRecorderParams = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
||||
import_validatorPrimitives.scheme.BrowserContextDisableRecorderResult = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
||||
import_validatorPrimitives.scheme.BrowserContextExposeConsoleApiParams = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
||||
import_validatorPrimitives.scheme.BrowserContextExposeConsoleApiResult = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
||||
import_validatorPrimitives.scheme.BrowserContextNewCDPSessionParams = (0, import_validatorPrimitives.tObject)({
|
||||
page: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tChannel)(["Page"])),
|
||||
frame: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tChannel)(["Frame"]))
|
||||
@@ -1490,6 +1493,25 @@ import_validatorPrimitives.scheme.PageUpdateSubscriptionParams = (0, import_vali
|
||||
enabled: import_validatorPrimitives.tBoolean
|
||||
});
|
||||
import_validatorPrimitives.scheme.PageUpdateSubscriptionResult = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
||||
import_validatorPrimitives.scheme.PageAgentParams = (0, import_validatorPrimitives.tObject)({
|
||||
api: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
||||
apiKey: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
||||
apiEndpoint: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
||||
apiTimeout: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
||||
apiCacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
||||
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
||||
cacheOutFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
||||
doNotRenderActive: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tBoolean),
|
||||
maxActions: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
||||
maxActionRetries: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
||||
maxTokens: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
||||
model: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
||||
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue"))),
|
||||
systemPrompt: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString)
|
||||
});
|
||||
import_validatorPrimitives.scheme.PageAgentResult = (0, import_validatorPrimitives.tObject)({
|
||||
agent: (0, import_validatorPrimitives.tChannel)(["PageAgent"])
|
||||
});
|
||||
import_validatorPrimitives.scheme.FrameInitializer = (0, import_validatorPrimitives.tObject)({
|
||||
url: import_validatorPrimitives.tString,
|
||||
name: import_validatorPrimitives.tString,
|
||||
@@ -2881,6 +2903,63 @@ import_validatorPrimitives.scheme.JsonPipeSendParams = (0, import_validatorPrimi
|
||||
import_validatorPrimitives.scheme.JsonPipeSendResult = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
||||
import_validatorPrimitives.scheme.JsonPipeCloseParams = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
||||
import_validatorPrimitives.scheme.JsonPipeCloseResult = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
||||
import_validatorPrimitives.scheme.PageAgentInitializer = (0, import_validatorPrimitives.tObject)({
|
||||
page: (0, import_validatorPrimitives.tChannel)(["Page"])
|
||||
});
|
||||
import_validatorPrimitives.scheme.PageAgentTurnEvent = (0, import_validatorPrimitives.tObject)({
|
||||
role: import_validatorPrimitives.tString,
|
||||
message: import_validatorPrimitives.tString,
|
||||
usage: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
||||
inputTokens: import_validatorPrimitives.tInt,
|
||||
outputTokens: import_validatorPrimitives.tInt
|
||||
}))
|
||||
});
|
||||
import_validatorPrimitives.scheme.PageAgentPerformParams = (0, import_validatorPrimitives.tObject)({
|
||||
task: import_validatorPrimitives.tString,
|
||||
maxActions: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
||||
maxActionRetries: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
||||
maxTokens: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
||||
cacheKey: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
||||
timeout: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt)
|
||||
});
|
||||
import_validatorPrimitives.scheme.PageAgentPerformResult = (0, import_validatorPrimitives.tObject)({
|
||||
usage: (0, import_validatorPrimitives.tType)("AgentUsage")
|
||||
});
|
||||
import_validatorPrimitives.scheme.PageAgentExpectParams = (0, import_validatorPrimitives.tObject)({
|
||||
expectation: import_validatorPrimitives.tString,
|
||||
maxActions: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
||||
maxActionRetries: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
||||
maxTokens: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
||||
cacheKey: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
||||
timeout: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt)
|
||||
});
|
||||
import_validatorPrimitives.scheme.PageAgentExpectResult = (0, import_validatorPrimitives.tObject)({
|
||||
usage: (0, import_validatorPrimitives.tType)("AgentUsage")
|
||||
});
|
||||
import_validatorPrimitives.scheme.PageAgentExtractParams = (0, import_validatorPrimitives.tObject)({
|
||||
query: import_validatorPrimitives.tString,
|
||||
schema: import_validatorPrimitives.tAny,
|
||||
maxActions: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
||||
maxActionRetries: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
||||
maxTokens: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
||||
cacheKey: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
||||
timeout: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt)
|
||||
});
|
||||
import_validatorPrimitives.scheme.PageAgentExtractResult = (0, import_validatorPrimitives.tObject)({
|
||||
result: import_validatorPrimitives.tAny,
|
||||
usage: (0, import_validatorPrimitives.tType)("AgentUsage")
|
||||
});
|
||||
import_validatorPrimitives.scheme.PageAgentDisposeParams = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
||||
import_validatorPrimitives.scheme.PageAgentDisposeResult = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
||||
import_validatorPrimitives.scheme.PageAgentUsageParams = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
||||
import_validatorPrimitives.scheme.PageAgentUsageResult = (0, import_validatorPrimitives.tObject)({
|
||||
usage: (0, import_validatorPrimitives.tType)("AgentUsage")
|
||||
});
|
||||
import_validatorPrimitives.scheme.AgentUsage = (0, import_validatorPrimitives.tObject)({
|
||||
turns: import_validatorPrimitives.tInt,
|
||||
inputTokens: import_validatorPrimitives.tInt,
|
||||
outputTokens: import_validatorPrimitives.tInt
|
||||
});
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
ValidationError,
|
||||
|
||||
3
node_modules/playwright-core/lib/remote/playwrightServer.js
generated
vendored
3
node_modules/playwright-core/lib/remote/playwrightServer.js
generated
vendored
@@ -321,8 +321,7 @@ const defaultLaunchOptions = {
|
||||
handleSIGINT: false,
|
||||
handleSIGTERM: false,
|
||||
handleSIGHUP: false,
|
||||
headless: true,
|
||||
devtools: false
|
||||
headless: true
|
||||
};
|
||||
const optionsThatAllowBrowserReuse = [
|
||||
"headless",
|
||||
|
||||
335
node_modules/playwright-core/lib/server/agent/actionRunner.js
generated
vendored
Normal file
335
node_modules/playwright-core/lib/server/agent/actionRunner.js
generated
vendored
Normal file
@@ -0,0 +1,335 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var actionRunner_exports = {};
|
||||
__export(actionRunner_exports, {
|
||||
runAction: () => runAction,
|
||||
traceParamsForAction: () => traceParamsForAction
|
||||
});
|
||||
module.exports = __toCommonJS(actionRunner_exports);
|
||||
var import_expectUtils = require("../utils/expectUtils");
|
||||
var import_urlMatch = require("../../utils/isomorphic/urlMatch");
|
||||
var import_stringUtils = require("../../utils/isomorphic/stringUtils");
|
||||
var import_time = require("../../utils/isomorphic/time");
|
||||
var import_crypto = require("../utils/crypto");
|
||||
var import_ariaSnapshot = require("../../utils/isomorphic/ariaSnapshot");
|
||||
var import_locatorGenerators = require("../../utils/isomorphic/locatorGenerators");
|
||||
var import_utilsBundle = require("../../utilsBundle");
|
||||
var import_errors = require("../errors");
|
||||
async function runAction(progress, mode, page, action, secrets) {
|
||||
const parentMetadata = progress.metadata;
|
||||
const frame = page.mainFrame();
|
||||
const callMetadata = callMetadataForAction(progress, frame, action, mode);
|
||||
callMetadata.log = parentMetadata.log;
|
||||
progress.metadata = callMetadata;
|
||||
await frame.instrumentation.onBeforeCall(frame, callMetadata, parentMetadata.id);
|
||||
let error;
|
||||
const result = await innerRunAction(progress, mode, page, action, secrets).catch((e) => error = e);
|
||||
callMetadata.endTime = (0, import_time.monotonicTime)();
|
||||
callMetadata.error = error ? (0, import_errors.serializeError)(error) : void 0;
|
||||
callMetadata.result = error ? void 0 : result;
|
||||
await frame.instrumentation.onAfterCall(frame, callMetadata);
|
||||
if (error)
|
||||
throw error;
|
||||
return result;
|
||||
}
|
||||
async function innerRunAction(progress, mode, page, action, secrets) {
|
||||
const frame = page.mainFrame();
|
||||
const commonOptions = { strict: true, noAutoWaiting: mode === "generate" };
|
||||
switch (action.method) {
|
||||
case "navigate":
|
||||
await frame.goto(progress, action.url);
|
||||
break;
|
||||
case "click":
|
||||
await frame.click(progress, action.selector, {
|
||||
button: action.button,
|
||||
clickCount: action.clickCount,
|
||||
modifiers: action.modifiers,
|
||||
...commonOptions
|
||||
});
|
||||
break;
|
||||
case "drag":
|
||||
await frame.dragAndDrop(progress, action.sourceSelector, action.targetSelector, { ...commonOptions });
|
||||
break;
|
||||
case "hover":
|
||||
await frame.hover(progress, action.selector, {
|
||||
modifiers: action.modifiers,
|
||||
...commonOptions
|
||||
});
|
||||
break;
|
||||
case "selectOption":
|
||||
await frame.selectOption(progress, action.selector, [], action.labels.map((a) => ({ label: a })), { ...commonOptions });
|
||||
break;
|
||||
case "pressKey":
|
||||
await page.keyboard.press(progress, action.key);
|
||||
break;
|
||||
case "pressSequentially": {
|
||||
const secret = secrets?.find((s) => s.name === action.text)?.value ?? action.text;
|
||||
await frame.type(progress, action.selector, secret, { ...commonOptions });
|
||||
if (action.submit)
|
||||
await page.keyboard.press(progress, "Enter");
|
||||
break;
|
||||
}
|
||||
case "fill": {
|
||||
const secret = secrets?.find((s) => s.name === action.text)?.value ?? action.text;
|
||||
await frame.fill(progress, action.selector, secret, { ...commonOptions });
|
||||
if (action.submit)
|
||||
await page.keyboard.press(progress, "Enter");
|
||||
break;
|
||||
}
|
||||
case "setChecked":
|
||||
if (action.checked)
|
||||
await frame.check(progress, action.selector, { ...commonOptions });
|
||||
else
|
||||
await frame.uncheck(progress, action.selector, { ...commonOptions });
|
||||
break;
|
||||
case "expectVisible": {
|
||||
await runExpect(frame, progress, mode, action.selector, { expression: "to.be.visible", isNot: !!action.isNot }, "visible", "toBeVisible", "");
|
||||
break;
|
||||
}
|
||||
case "expectValue": {
|
||||
if (action.type === "textbox" || action.type === "combobox" || action.type === "slider") {
|
||||
const expectedText = (0, import_expectUtils.serializeExpectedTextValues)([action.value]);
|
||||
await runExpect(frame, progress, mode, action.selector, { expression: "to.have.value", expectedText, isNot: !!action.isNot }, action.value, "toHaveValue", "expected");
|
||||
} else if (action.type === "checkbox" || action.type === "radio") {
|
||||
const expectedValue = { checked: action.value === "true" };
|
||||
await runExpect(frame, progress, mode, action.selector, { selector: action.selector, expression: "to.be.checked", expectedValue, isNot: !!action.isNot }, action.value ? "checked" : "unchecked", "toBeChecked", "");
|
||||
} else {
|
||||
throw new Error(`Unsupported element type: ${action.type}`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "expectAria": {
|
||||
const expectedValue = (0, import_ariaSnapshot.parseAriaSnapshotUnsafe)(import_utilsBundle.yaml, action.template);
|
||||
await runExpect(frame, progress, mode, "body", { expression: "to.match.aria", expectedValue, isNot: !!action.isNot }, "\n" + action.template, "toMatchAriaSnapshot", "expected");
|
||||
break;
|
||||
}
|
||||
case "expectURL": {
|
||||
if (!action.regex && !action.value)
|
||||
throw new Error("Either url or regex must be provided");
|
||||
if (action.regex && action.value)
|
||||
throw new Error("Only one of url or regex can be provided");
|
||||
const expected = action.regex ? (0, import_stringUtils.parseRegex)(action.regex) : (0, import_urlMatch.constructURLBasedOnBaseURL)(page.browserContext._options.baseURL, action.value);
|
||||
const expectedText = (0, import_expectUtils.serializeExpectedTextValues)([expected]);
|
||||
await runExpect(frame, progress, mode, void 0, { expression: "to.have.url", expectedText, isNot: !!action.isNot }, expected, "toHaveURL", "expected");
|
||||
break;
|
||||
}
|
||||
case "expectTitle": {
|
||||
const expectedText = (0, import_expectUtils.serializeExpectedTextValues)([action.value], { normalizeWhiteSpace: true });
|
||||
await runExpect(frame, progress, mode, void 0, { expression: "to.have.title", expectedText, isNot: !!action.isNot }, action.value, "toHaveTitle", "expected");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
async function runExpect(frame, progress, mode, selector, options, expected, matcherName, expectation) {
|
||||
const result = await frame.expect(progress, selector, {
|
||||
...options,
|
||||
// When generating, we want the expect to pass or fail immediately and give feedback to the model.
|
||||
noAutoWaiting: mode === "generate",
|
||||
timeoutForLogs: mode === "generate" ? void 0 : progress.timeout
|
||||
});
|
||||
if (!result.matches === !options.isNot) {
|
||||
const received = matcherName === "toMatchAriaSnapshot" ? "\n" + result.received.raw : result.received;
|
||||
const expectedSuffix = typeof expected === "string" ? "" : " pattern";
|
||||
const expectedDisplay = typeof expected === "string" ? expected : expected.toString();
|
||||
throw new Error((0, import_expectUtils.formatMatcherMessage)(import_expectUtils.simpleMatcherUtils, {
|
||||
isNot: options.isNot,
|
||||
matcherName,
|
||||
expectation,
|
||||
locator: selector ? (0, import_locatorGenerators.asLocatorDescription)("javascript", selector) : void 0,
|
||||
timedOut: result.timedOut,
|
||||
timeout: mode === "generate" ? void 0 : progress.timeout,
|
||||
printedExpected: options.isNot ? `Expected${expectedSuffix}: not ${expectedDisplay}` : `Expected${expectedSuffix}: ${expectedDisplay}`,
|
||||
printedReceived: result.errorMessage ? "" : `Received: ${received}`,
|
||||
errorMessage: result.errorMessage
|
||||
// Note: we are not passing call log, because it will be automatically appended on the client side,
|
||||
// as a part of the agent.{perform,expect} call.
|
||||
}));
|
||||
}
|
||||
}
|
||||
function traceParamsForAction(progress, action, mode) {
|
||||
const timeout = progress.timeout;
|
||||
switch (action.method) {
|
||||
case "navigate": {
|
||||
const params = {
|
||||
url: action.url,
|
||||
timeout
|
||||
};
|
||||
return { type: "Frame", method: "goto", params };
|
||||
}
|
||||
case "click": {
|
||||
const params = {
|
||||
selector: action.selector,
|
||||
strict: true,
|
||||
modifiers: action.modifiers,
|
||||
button: action.button,
|
||||
clickCount: action.clickCount,
|
||||
timeout
|
||||
};
|
||||
return { type: "Frame", method: "click", params };
|
||||
}
|
||||
case "drag": {
|
||||
const params = {
|
||||
source: action.sourceSelector,
|
||||
target: action.targetSelector,
|
||||
timeout
|
||||
};
|
||||
return { type: "Frame", method: "dragAndDrop", params };
|
||||
}
|
||||
case "hover": {
|
||||
const params = {
|
||||
selector: action.selector,
|
||||
modifiers: action.modifiers,
|
||||
timeout
|
||||
};
|
||||
return { type: "Frame", method: "hover", params };
|
||||
}
|
||||
case "pressKey": {
|
||||
const params = {
|
||||
key: action.key
|
||||
};
|
||||
return { type: "Page", method: "keyboardPress", params };
|
||||
}
|
||||
case "pressSequentially": {
|
||||
const params = {
|
||||
selector: action.selector,
|
||||
text: action.text,
|
||||
timeout
|
||||
};
|
||||
return { type: "Frame", method: "type", params };
|
||||
}
|
||||
case "fill": {
|
||||
const params = {
|
||||
selector: action.selector,
|
||||
strict: true,
|
||||
value: action.text,
|
||||
timeout
|
||||
};
|
||||
return { type: "Frame", method: "fill", params };
|
||||
}
|
||||
case "setChecked": {
|
||||
if (action.checked) {
|
||||
const params = {
|
||||
selector: action.selector,
|
||||
strict: true,
|
||||
timeout
|
||||
};
|
||||
return { type: "Frame", method: "check", params };
|
||||
} else {
|
||||
const params = {
|
||||
selector: action.selector,
|
||||
strict: true,
|
||||
timeout
|
||||
};
|
||||
return { type: "Frame", method: "uncheck", params };
|
||||
}
|
||||
}
|
||||
case "selectOption": {
|
||||
const params = {
|
||||
selector: action.selector,
|
||||
strict: true,
|
||||
options: action.labels.map((label) => ({ label })),
|
||||
timeout
|
||||
};
|
||||
return { type: "Frame", method: "selectOption", params };
|
||||
}
|
||||
case "expectValue": {
|
||||
if (action.type === "textbox" || action.type === "combobox" || action.type === "slider") {
|
||||
const expectedText = (0, import_expectUtils.serializeExpectedTextValues)([action.value]);
|
||||
const params = {
|
||||
selector: action.selector,
|
||||
expression: "to.have.value",
|
||||
expectedText,
|
||||
isNot: !!action.isNot,
|
||||
timeout
|
||||
};
|
||||
return { type: "Frame", method: "expect", title: "Expect Value", params };
|
||||
} else if (action.type === "checkbox" || action.type === "radio") {
|
||||
const params = {
|
||||
selector: action.selector,
|
||||
expression: "to.be.checked",
|
||||
isNot: !!action.isNot,
|
||||
timeout
|
||||
};
|
||||
return { type: "Frame", method: "expect", title: "Expect Checked", params };
|
||||
} else {
|
||||
throw new Error(`Unsupported element type: ${action.type}`);
|
||||
}
|
||||
}
|
||||
case "expectVisible": {
|
||||
const params = {
|
||||
selector: action.selector,
|
||||
expression: "to.be.visible",
|
||||
isNot: !!action.isNot,
|
||||
timeout
|
||||
};
|
||||
return { type: "Frame", method: "expect", title: "Expect Visible", params };
|
||||
}
|
||||
case "expectAria": {
|
||||
const params = {
|
||||
selector: "body",
|
||||
expression: "to.match.snapshot",
|
||||
expectedText: [],
|
||||
isNot: !!action.isNot,
|
||||
timeout
|
||||
};
|
||||
return { type: "Frame", method: "expect", title: "Expect Aria Snapshot", params };
|
||||
}
|
||||
case "expectURL": {
|
||||
const expected = action.regex ? (0, import_stringUtils.parseRegex)(action.regex) : action.value;
|
||||
const expectedText = (0, import_expectUtils.serializeExpectedTextValues)([expected]);
|
||||
const params = {
|
||||
selector: void 0,
|
||||
expression: "to.have.url",
|
||||
expectedText,
|
||||
isNot: !!action.isNot,
|
||||
timeout
|
||||
};
|
||||
return { type: "Frame", method: "expect", title: "Expect URL", params };
|
||||
}
|
||||
case "expectTitle": {
|
||||
const expectedText = (0, import_expectUtils.serializeExpectedTextValues)([action.value], { normalizeWhiteSpace: true });
|
||||
const params = {
|
||||
selector: void 0,
|
||||
expression: "to.have.title",
|
||||
expectedText,
|
||||
isNot: !!action.isNot,
|
||||
timeout
|
||||
};
|
||||
return { type: "Frame", method: "expect", title: "Expect Title", params };
|
||||
}
|
||||
}
|
||||
}
|
||||
function callMetadataForAction(progress, frame, action, mode) {
|
||||
const callMetadata = {
|
||||
id: `call@${(0, import_crypto.createGuid)()}`,
|
||||
objectId: frame.guid,
|
||||
pageId: frame._page.guid,
|
||||
frameId: frame.guid,
|
||||
startTime: (0, import_time.monotonicTime)(),
|
||||
endTime: 0,
|
||||
log: [],
|
||||
...traceParamsForAction(progress, action, mode)
|
||||
};
|
||||
return callMetadata;
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
runAction,
|
||||
traceParamsForAction
|
||||
});
|
||||
128
node_modules/playwright-core/lib/server/agent/actions.js
generated
vendored
Normal file
128
node_modules/playwright-core/lib/server/agent/actions.js
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var actions_exports = {};
|
||||
__export(actions_exports, {
|
||||
cachedActionsSchema: () => cachedActionsSchema
|
||||
});
|
||||
module.exports = __toCommonJS(actions_exports);
|
||||
var import_mcpBundle = require("../../mcpBundle");
|
||||
const modifiersSchema = import_mcpBundle.z.array(
|
||||
import_mcpBundle.z.enum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"])
|
||||
);
|
||||
const navigateActionSchema = import_mcpBundle.z.object({
|
||||
method: import_mcpBundle.z.literal("navigate"),
|
||||
url: import_mcpBundle.z.string()
|
||||
});
|
||||
const clickActionSchema = import_mcpBundle.z.object({
|
||||
method: import_mcpBundle.z.literal("click"),
|
||||
selector: import_mcpBundle.z.string(),
|
||||
button: import_mcpBundle.z.enum(["left", "right", "middle"]).optional(),
|
||||
clickCount: import_mcpBundle.z.number().optional(),
|
||||
modifiers: modifiersSchema.optional()
|
||||
});
|
||||
const dragActionSchema = import_mcpBundle.z.object({
|
||||
method: import_mcpBundle.z.literal("drag"),
|
||||
sourceSelector: import_mcpBundle.z.string(),
|
||||
targetSelector: import_mcpBundle.z.string()
|
||||
});
|
||||
const hoverActionSchema = import_mcpBundle.z.object({
|
||||
method: import_mcpBundle.z.literal("hover"),
|
||||
selector: import_mcpBundle.z.string(),
|
||||
modifiers: modifiersSchema.optional()
|
||||
});
|
||||
const selectOptionActionSchema = import_mcpBundle.z.object({
|
||||
method: import_mcpBundle.z.literal("selectOption"),
|
||||
selector: import_mcpBundle.z.string(),
|
||||
labels: import_mcpBundle.z.array(import_mcpBundle.z.string())
|
||||
});
|
||||
const pressActionSchema = import_mcpBundle.z.object({
|
||||
method: import_mcpBundle.z.literal("pressKey"),
|
||||
key: import_mcpBundle.z.string()
|
||||
});
|
||||
const pressSequentiallyActionSchema = import_mcpBundle.z.object({
|
||||
method: import_mcpBundle.z.literal("pressSequentially"),
|
||||
selector: import_mcpBundle.z.string(),
|
||||
text: import_mcpBundle.z.string(),
|
||||
submit: import_mcpBundle.z.boolean().optional()
|
||||
});
|
||||
const fillActionSchema = import_mcpBundle.z.object({
|
||||
method: import_mcpBundle.z.literal("fill"),
|
||||
selector: import_mcpBundle.z.string(),
|
||||
text: import_mcpBundle.z.string(),
|
||||
submit: import_mcpBundle.z.boolean().optional()
|
||||
});
|
||||
const setCheckedSchema = import_mcpBundle.z.object({
|
||||
method: import_mcpBundle.z.literal("setChecked"),
|
||||
selector: import_mcpBundle.z.string(),
|
||||
checked: import_mcpBundle.z.boolean()
|
||||
});
|
||||
const expectVisibleSchema = import_mcpBundle.z.object({
|
||||
method: import_mcpBundle.z.literal("expectVisible"),
|
||||
selector: import_mcpBundle.z.string(),
|
||||
isNot: import_mcpBundle.z.boolean().optional()
|
||||
});
|
||||
const expectValueSchema = import_mcpBundle.z.object({
|
||||
method: import_mcpBundle.z.literal("expectValue"),
|
||||
selector: import_mcpBundle.z.string(),
|
||||
type: import_mcpBundle.z.enum(["textbox", "checkbox", "radio", "combobox", "slider"]),
|
||||
value: import_mcpBundle.z.string(),
|
||||
isNot: import_mcpBundle.z.boolean().optional()
|
||||
});
|
||||
const expectAriaSchema = import_mcpBundle.z.object({
|
||||
method: import_mcpBundle.z.literal("expectAria"),
|
||||
template: import_mcpBundle.z.string(),
|
||||
isNot: import_mcpBundle.z.boolean().optional()
|
||||
});
|
||||
const expectURLSchema = import_mcpBundle.z.object({
|
||||
method: import_mcpBundle.z.literal("expectURL"),
|
||||
value: import_mcpBundle.z.string().optional(),
|
||||
regex: import_mcpBundle.z.string().optional(),
|
||||
isNot: import_mcpBundle.z.boolean().optional()
|
||||
});
|
||||
const expectTitleSchema = import_mcpBundle.z.object({
|
||||
method: import_mcpBundle.z.literal("expectTitle"),
|
||||
value: import_mcpBundle.z.string(),
|
||||
isNot: import_mcpBundle.z.boolean().optional()
|
||||
});
|
||||
const actionSchema = import_mcpBundle.z.discriminatedUnion("method", [
|
||||
navigateActionSchema,
|
||||
clickActionSchema,
|
||||
dragActionSchema,
|
||||
hoverActionSchema,
|
||||
selectOptionActionSchema,
|
||||
pressActionSchema,
|
||||
pressSequentiallyActionSchema,
|
||||
fillActionSchema,
|
||||
setCheckedSchema,
|
||||
expectVisibleSchema,
|
||||
expectValueSchema,
|
||||
expectAriaSchema,
|
||||
expectURLSchema,
|
||||
expectTitleSchema
|
||||
]);
|
||||
const actionWithCodeSchema = actionSchema.and(import_mcpBundle.z.object({
|
||||
code: import_mcpBundle.z.string()
|
||||
}));
|
||||
const cachedActionsSchema = import_mcpBundle.z.record(import_mcpBundle.z.string(), import_mcpBundle.z.object({
|
||||
actions: import_mcpBundle.z.array(actionWithCodeSchema)
|
||||
}));
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
cachedActionsSchema
|
||||
});
|
||||
111
node_modules/playwright-core/lib/server/agent/codegen.js
generated
vendored
Normal file
111
node_modules/playwright-core/lib/server/agent/codegen.js
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var codegen_exports = {};
|
||||
__export(codegen_exports, {
|
||||
generateCode: () => generateCode
|
||||
});
|
||||
module.exports = __toCommonJS(codegen_exports);
|
||||
var import_locatorGenerators = require("../../utils/isomorphic/locatorGenerators");
|
||||
var import_stringUtils = require("../../utils/isomorphic/stringUtils");
|
||||
async function generateCode(sdkLanguage, action) {
|
||||
switch (action.method) {
|
||||
case "navigate": {
|
||||
return `await page.goto(${(0, import_stringUtils.escapeWithQuotes)(action.url)});`;
|
||||
}
|
||||
case "click": {
|
||||
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
|
||||
return `await page.${locator}.click(${(0, import_stringUtils.formatObjectOrVoid)({
|
||||
button: action.button,
|
||||
clickCount: action.clickCount,
|
||||
modifiers: action.modifiers
|
||||
})});`;
|
||||
}
|
||||
case "drag": {
|
||||
const sourceLocator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.sourceSelector);
|
||||
const targetLocator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.targetSelector);
|
||||
return `await page.${sourceLocator}.dragAndDrop(${targetLocator});`;
|
||||
}
|
||||
case "hover": {
|
||||
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
|
||||
return `await page.${locator}.hover(${(0, import_stringUtils.formatObjectOrVoid)({
|
||||
modifiers: action.modifiers
|
||||
})});`;
|
||||
}
|
||||
case "pressKey": {
|
||||
return `await page.keyboard.press(${(0, import_stringUtils.escapeWithQuotes)(action.key, "'")});`;
|
||||
}
|
||||
case "selectOption": {
|
||||
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
|
||||
return `await page.${locator}.selectOption(${action.labels.length === 1 ? (0, import_stringUtils.escapeWithQuotes)(action.labels[0]) : "[" + action.labels.map((label) => (0, import_stringUtils.escapeWithQuotes)(label)).join(", ") + "]"});`;
|
||||
}
|
||||
case "pressSequentially": {
|
||||
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
|
||||
const code = [`await page.${locator}.pressSequentially(${(0, import_stringUtils.escapeWithQuotes)(action.text)});`];
|
||||
if (action.submit)
|
||||
code.push(`await page.keyboard.press('Enter');`);
|
||||
return code.join("\n");
|
||||
}
|
||||
case "fill": {
|
||||
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
|
||||
const code = [`await page.${locator}.fill(${(0, import_stringUtils.escapeWithQuotes)(action.text)});`];
|
||||
if (action.submit)
|
||||
code.push(`await page.keyboard.press('Enter');`);
|
||||
return code.join("\n");
|
||||
}
|
||||
case "setChecked": {
|
||||
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
|
||||
if (action.checked)
|
||||
return `await page.${locator}.check();`;
|
||||
else
|
||||
return `await page.${locator}.uncheck();`;
|
||||
}
|
||||
case "expectVisible": {
|
||||
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
|
||||
const notInfix = action.isNot ? "not." : "";
|
||||
return `await expect(page.${locator}).${notInfix}toBeVisible();`;
|
||||
}
|
||||
case "expectValue": {
|
||||
const notInfix = action.isNot ? "not." : "";
|
||||
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
|
||||
if (action.type === "checkbox" || action.type === "radio")
|
||||
return `await expect(page.${locator}).${notInfix}toBeChecked({ checked: ${action.value === "true"} });`;
|
||||
return `await expect(page.${locator}).${notInfix}toHaveValue(${(0, import_stringUtils.escapeWithQuotes)(action.value)});`;
|
||||
}
|
||||
case "expectAria": {
|
||||
const notInfix = action.isNot ? "not." : "";
|
||||
return `await expect(page.locator('body')).${notInfix}toMatchAria(\`
|
||||
${(0, import_stringUtils.escapeTemplateString)(action.template)}
|
||||
\`);`;
|
||||
}
|
||||
case "expectURL": {
|
||||
const arg = action.regex ? (0, import_stringUtils.parseRegex)(action.regex).toString() : (0, import_stringUtils.escapeWithQuotes)(action.value);
|
||||
const notInfix = action.isNot ? "not." : "";
|
||||
return `await expect(page).${notInfix}toHaveURL(${arg});`;
|
||||
}
|
||||
case "expectTitle": {
|
||||
const notInfix = action.isNot ? "not." : "";
|
||||
return `await expect(page).${notInfix}toHaveTitle(${(0, import_stringUtils.escapeWithQuotes)(action.value)});`;
|
||||
}
|
||||
}
|
||||
throw new Error("Unknown action " + action.method);
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
generateCode
|
||||
});
|
||||
150
node_modules/playwright-core/lib/server/agent/context.js
generated
vendored
Normal file
150
node_modules/playwright-core/lib/server/agent/context.js
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var context_exports = {};
|
||||
__export(context_exports, {
|
||||
Context: () => Context
|
||||
});
|
||||
module.exports = __toCommonJS(context_exports);
|
||||
var import_browserContext = require("../browserContext");
|
||||
var import_actionRunner = require("./actionRunner");
|
||||
var import_codegen = require("./codegen");
|
||||
var import_stringUtils = require("../../utils/isomorphic/stringUtils");
|
||||
class Context {
|
||||
constructor(page, agentParams, events) {
|
||||
this._actions = [];
|
||||
this._history = [];
|
||||
this.page = page;
|
||||
this.agentParams = agentParams;
|
||||
this.sdkLanguage = page.browserContext._browser.sdkLanguage();
|
||||
this.events = events;
|
||||
this._budget = { tokens: agentParams.maxTokens };
|
||||
}
|
||||
async runActionAndWait(progress, action) {
|
||||
return await this.runActionsAndWait(progress, [action]);
|
||||
}
|
||||
async runActionsAndWait(progress, action, options) {
|
||||
const error = await this.waitForCompletion(progress, async () => {
|
||||
for (const a of action) {
|
||||
await (0, import_actionRunner.runAction)(progress, "generate", this.page, a, this.agentParams?.secrets ?? []);
|
||||
const code = await (0, import_codegen.generateCode)(this.sdkLanguage, a);
|
||||
this._actions.push({ ...a, code });
|
||||
}
|
||||
return void 0;
|
||||
}, options).catch((error2) => error2);
|
||||
return await this.snapshotResult(progress, error);
|
||||
}
|
||||
async runActionNoWait(progress, action) {
|
||||
return await this.runActionsAndWait(progress, [action], { noWait: true });
|
||||
}
|
||||
actions() {
|
||||
return this._actions.slice();
|
||||
}
|
||||
history() {
|
||||
return this._history;
|
||||
}
|
||||
pushHistory(item) {
|
||||
this._history.push(item);
|
||||
this._actions = [];
|
||||
}
|
||||
consumeTokens(tokens) {
|
||||
if (this._budget.tokens === void 0)
|
||||
return;
|
||||
this._budget.tokens = Math.max(0, this._budget.tokens - tokens);
|
||||
}
|
||||
maxTokensRemaining() {
|
||||
return this._budget.tokens;
|
||||
}
|
||||
async waitForCompletion(progress, callback, options) {
|
||||
if (options?.noWait)
|
||||
return await callback();
|
||||
const requests = [];
|
||||
const requestListener = (request) => requests.push(request);
|
||||
const disposeListeners = () => {
|
||||
this.page.browserContext.off(import_browserContext.BrowserContext.Events.Request, requestListener);
|
||||
};
|
||||
this.page.browserContext.on(import_browserContext.BrowserContext.Events.Request, requestListener);
|
||||
let result;
|
||||
try {
|
||||
result = await callback();
|
||||
await progress.wait(500);
|
||||
} finally {
|
||||
disposeListeners();
|
||||
}
|
||||
const requestedNavigation = requests.some((request) => request.isNavigationRequest());
|
||||
if (requestedNavigation) {
|
||||
await this.page.mainFrame().waitForLoadState(progress, "load");
|
||||
return result;
|
||||
}
|
||||
const promises = [];
|
||||
for (const request of requests) {
|
||||
if (["document", "stylesheet", "script", "xhr", "fetch"].includes(request.resourceType()))
|
||||
promises.push(request.response().then((r) => r?.finished()));
|
||||
else
|
||||
promises.push(request.response());
|
||||
}
|
||||
await progress.race([...promises, progress.wait(5e3)]);
|
||||
if (!promises.length)
|
||||
await progress.wait(500);
|
||||
return result;
|
||||
}
|
||||
async takeSnapshot(progress) {
|
||||
const { full } = await this.page.snapshotForAI(progress, { doNotRenderActive: this.agentParams.doNotRenderActive });
|
||||
return full;
|
||||
}
|
||||
async snapshotResult(progress, error) {
|
||||
const snapshot = this._redactText(await this.takeSnapshot(progress));
|
||||
const text = [];
|
||||
if (error)
|
||||
text.push(`# Error
|
||||
${(0, import_stringUtils.stripAnsiEscapes)(error.message)}`);
|
||||
else
|
||||
text.push(`# Success`);
|
||||
text.push(`# Page snapshot
|
||||
${snapshot}`);
|
||||
return {
|
||||
isError: !!error,
|
||||
content: [{ type: "text", text: text.join("\n\n") }]
|
||||
};
|
||||
}
|
||||
async refSelectors(progress, params) {
|
||||
return Promise.all(params.map(async (param) => {
|
||||
try {
|
||||
const { resolvedSelector } = await this.page.mainFrame().resolveSelector(progress, `aria-ref=${param.ref}`);
|
||||
return resolvedSelector;
|
||||
} catch (e) {
|
||||
throw new Error(`Ref ${param.ref} not found in the current page snapshot. Try capturing new snapshot.`);
|
||||
}
|
||||
}));
|
||||
}
|
||||
_redactText(text) {
|
||||
const secrets = this.agentParams?.secrets;
|
||||
if (!secrets)
|
||||
return text;
|
||||
const redactText = (text2) => {
|
||||
for (const { name, value } of secrets)
|
||||
text2 = text2.replaceAll(value, `<secret>${name}</secret>`);
|
||||
return text2;
|
||||
};
|
||||
return redactText(text);
|
||||
}
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
Context
|
||||
});
|
||||
156
node_modules/playwright-core/lib/server/agent/expectTools.js
generated
vendored
Normal file
156
node_modules/playwright-core/lib/server/agent/expectTools.js
generated
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var expectTools_exports = {};
|
||||
__export(expectTools_exports, {
|
||||
default: () => expectTools_default
|
||||
});
|
||||
module.exports = __toCommonJS(expectTools_exports);
|
||||
var import_mcpBundle = require("../../mcpBundle");
|
||||
var import_locatorUtils = require("../../utils/isomorphic/locatorUtils");
|
||||
var import_yaml = require("../../utils/isomorphic/yaml");
|
||||
var import_tool = require("./tool");
|
||||
const expectVisible = (0, import_tool.defineTool)({
|
||||
schema: {
|
||||
name: "browser_expect_visible",
|
||||
title: "Expect element visible",
|
||||
description: "Expect element is visible on the page",
|
||||
inputSchema: import_mcpBundle.z.object({
|
||||
role: import_mcpBundle.z.string().describe('ROLE of the element. Can be found in the snapshot like this: `- {ROLE} "Accessible Name":`'),
|
||||
accessibleName: import_mcpBundle.z.string().describe('ACCESSIBLE_NAME of the element. Can be found in the snapshot like this: `- role "{ACCESSIBLE_NAME}"`'),
|
||||
isNot: import_mcpBundle.z.boolean().optional().describe("Expect the opposite")
|
||||
})
|
||||
},
|
||||
handle: async (progress, context, params) => {
|
||||
return await context.runActionAndWait(progress, {
|
||||
method: "expectVisible",
|
||||
selector: (0, import_locatorUtils.getByRoleSelector)(params.role, { name: params.accessibleName }),
|
||||
isNot: params.isNot
|
||||
});
|
||||
}
|
||||
});
|
||||
const expectVisibleText = (0, import_tool.defineTool)({
|
||||
schema: {
|
||||
name: "browser_expect_visible_text",
|
||||
title: "Expect text visible",
|
||||
description: `Expect text is visible on the page. Prefer ${expectVisible.schema.name} if possible.`,
|
||||
inputSchema: import_mcpBundle.z.object({
|
||||
text: import_mcpBundle.z.string().describe('TEXT to expect. Can be found in the snapshot like this: `- role "Accessible Name": {TEXT}` or like this: `- text: {TEXT}`'),
|
||||
isNot: import_mcpBundle.z.boolean().optional().describe("Expect the opposite")
|
||||
})
|
||||
},
|
||||
handle: async (progress, context, params) => {
|
||||
return await context.runActionAndWait(progress, {
|
||||
method: "expectVisible",
|
||||
selector: (0, import_locatorUtils.getByTextSelector)(params.text),
|
||||
isNot: params.isNot
|
||||
});
|
||||
}
|
||||
});
|
||||
const expectValue = (0, import_tool.defineTool)({
|
||||
schema: {
|
||||
name: "browser_expect_value",
|
||||
title: "Expect value",
|
||||
description: "Expect element value",
|
||||
inputSchema: import_mcpBundle.z.object({
|
||||
type: import_mcpBundle.z.enum(["textbox", "checkbox", "radio", "combobox", "slider"]).describe("Type of the element"),
|
||||
element: import_mcpBundle.z.string().describe("Human-readable element description"),
|
||||
ref: import_mcpBundle.z.string().describe("Exact target element reference from the page snapshot"),
|
||||
value: import_mcpBundle.z.string().describe('Value to expect. For checkbox, use "true" or "false".'),
|
||||
isNot: import_mcpBundle.z.boolean().optional().describe("Expect the opposite")
|
||||
})
|
||||
},
|
||||
handle: async (progress, context, params) => {
|
||||
const [selector] = await context.refSelectors(progress, [{ ref: params.ref, element: params.element }]);
|
||||
return await context.runActionAndWait(progress, {
|
||||
method: "expectValue",
|
||||
selector,
|
||||
type: params.type,
|
||||
value: params.value,
|
||||
isNot: params.isNot
|
||||
});
|
||||
}
|
||||
});
|
||||
const expectList = (0, import_tool.defineTool)({
|
||||
schema: {
|
||||
name: "browser_expect_list_visible",
|
||||
title: "Expect list visible",
|
||||
description: "Expect list is visible on the page, ensures items are present in the element in the exact order",
|
||||
inputSchema: import_mcpBundle.z.object({
|
||||
listRole: import_mcpBundle.z.string().describe("Aria role of the list element as in the snapshot"),
|
||||
listAccessibleName: import_mcpBundle.z.string().optional().describe("Accessible name of the list element as in the snapshot"),
|
||||
itemRole: import_mcpBundle.z.string().describe("Aria role of the list items as in the snapshot, should all be the same"),
|
||||
items: import_mcpBundle.z.array(import_mcpBundle.z.string().describe("Text to look for in the list item, can be either from accessible name of self / nested text content")),
|
||||
isNot: import_mcpBundle.z.boolean().optional().describe("Expect the opposite")
|
||||
})
|
||||
},
|
||||
handle: async (progress, context, params) => {
|
||||
const template = `- ${params.listRole}:
|
||||
${params.items.map((item) => ` - ${params.itemRole}: ${(0, import_yaml.yamlEscapeValueIfNeeded)(item)}`).join("\n")}`;
|
||||
return await context.runActionAndWait(progress, {
|
||||
method: "expectAria",
|
||||
template
|
||||
});
|
||||
}
|
||||
});
|
||||
const expectURL = (0, import_tool.defineTool)({
|
||||
schema: {
|
||||
name: "browser_expect_url",
|
||||
title: "Expect URL",
|
||||
description: "Expect the page URL to match the expected value. Either provide a url string or a regex pattern.",
|
||||
inputSchema: import_mcpBundle.z.object({
|
||||
url: import_mcpBundle.z.string().optional().describe("Expected URL string. Relative URLs are resolved against the baseURL."),
|
||||
regex: import_mcpBundle.z.string().optional().describe("Regular expression pattern to match the URL against, e.g. /foo.*/i."),
|
||||
isNot: import_mcpBundle.z.boolean().optional().describe("Expect the opposite")
|
||||
})
|
||||
},
|
||||
handle: async (progress, context, params) => {
|
||||
return await context.runActionAndWait(progress, {
|
||||
method: "expectURL",
|
||||
value: params.url,
|
||||
regex: params.regex,
|
||||
isNot: params.isNot
|
||||
});
|
||||
}
|
||||
});
|
||||
const expectTitle = (0, import_tool.defineTool)({
|
||||
schema: {
|
||||
name: "browser_expect_title",
|
||||
title: "Expect title",
|
||||
description: "Expect the page title to match the expected value.",
|
||||
inputSchema: import_mcpBundle.z.object({
|
||||
title: import_mcpBundle.z.string().describe("Expected page title."),
|
||||
isNot: import_mcpBundle.z.boolean().optional().describe("Expect the opposite")
|
||||
})
|
||||
},
|
||||
handle: async (progress, context, params) => {
|
||||
return await context.runActionAndWait(progress, {
|
||||
method: "expectTitle",
|
||||
value: params.title,
|
||||
isNot: params.isNot
|
||||
});
|
||||
}
|
||||
});
|
||||
var expectTools_default = [
|
||||
expectVisible,
|
||||
expectVisibleText,
|
||||
expectValue,
|
||||
expectList,
|
||||
expectURL,
|
||||
expectTitle
|
||||
];
|
||||
204
node_modules/playwright-core/lib/server/agent/pageAgent.js
generated
vendored
Normal file
204
node_modules/playwright-core/lib/server/agent/pageAgent.js
generated
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
"use strict";
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||
// If the importer is in node compatibility mode or this is not an ESM
|
||||
// file that has been converted to a CommonJS file using a Babel-
|
||||
// compatible transform (i.e. "__esModule" has not been set), then set
|
||||
// "default" to the CommonJS "module.exports" for node compatibility.
|
||||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||
mod
|
||||
));
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var pageAgent_exports = {};
|
||||
__export(pageAgent_exports, {
|
||||
pageAgentExpect: () => pageAgentExpect,
|
||||
pageAgentExtract: () => pageAgentExtract,
|
||||
pageAgentPerform: () => pageAgentPerform
|
||||
});
|
||||
module.exports = __toCommonJS(pageAgent_exports);
|
||||
var import_fs = __toESM(require("fs"));
|
||||
var import_path = __toESM(require("path"));
|
||||
var import_tool = require("./tool");
|
||||
var import_utilsBundle = require("../../utilsBundle");
|
||||
var import_mcpBundle = require("../../mcpBundle");
|
||||
var import_actionRunner = require("./actionRunner");
|
||||
var import_performTools = __toESM(require("./performTools"));
|
||||
var import_expectTools = __toESM(require("./expectTools"));
|
||||
var actions = __toESM(require("./actions"));
|
||||
async function pageAgentPerform(progress, context, userTask, callParams) {
|
||||
const cacheKey = (callParams.cacheKey ?? userTask).trim();
|
||||
if (await cachedPerform(progress, context, cacheKey))
|
||||
return;
|
||||
const task = `
|
||||
### Instructions
|
||||
- Perform the following task on the page.
|
||||
- Your reply should be a tool call that performs action the page".
|
||||
|
||||
### Task
|
||||
${userTask}
|
||||
`;
|
||||
progress.disableTimeout();
|
||||
await runLoop(progress, context, import_performTools.default, task, void 0, callParams);
|
||||
await updateCache(context, cacheKey);
|
||||
}
|
||||
async function pageAgentExpect(progress, context, expectation, callParams) {
|
||||
const cacheKey = (callParams.cacheKey ?? expectation).trim();
|
||||
if (await cachedPerform(progress, context, cacheKey))
|
||||
return;
|
||||
const task = `
|
||||
### Instructions
|
||||
- Call one of the "browser_expect_*" tools to verify / assert the condition.
|
||||
- You can call exactly one tool and it can't be report_results, must be one of the assertion tools.
|
||||
|
||||
### Expectation
|
||||
${expectation}
|
||||
`;
|
||||
progress.disableTimeout();
|
||||
await runLoop(progress, context, import_expectTools.default, task, void 0, callParams);
|
||||
await updateCache(context, cacheKey);
|
||||
}
|
||||
async function pageAgentExtract(progress, context, query, schema, callParams) {
|
||||
const task = `
|
||||
### Instructions
|
||||
Extract the following information from the page. Do not perform any actions, just extract the information.
|
||||
|
||||
### Query
|
||||
${query}`;
|
||||
const { result } = await runLoop(progress, context, [], task, schema, callParams);
|
||||
return result;
|
||||
}
|
||||
async function runLoop(progress, context, toolDefinitions, userTask, resultSchema, params) {
|
||||
if (!context.agentParams.api || !context.agentParams.model)
|
||||
throw new Error(`This action requires the API and API key to be set on the page agent. Did you mean to --run-agents=missing?`);
|
||||
if (!context.agentParams.apiKey)
|
||||
throw new Error(`This action requires API key to be set on the page agent.`);
|
||||
if (context.agentParams.apiEndpoint && !URL.canParse(context.agentParams.apiEndpoint))
|
||||
throw new Error(`Agent API endpoint "${context.agentParams.apiEndpoint}" is not a valid URL.`);
|
||||
const snapshot = await context.takeSnapshot(progress);
|
||||
const { tools, callTool, reportedResult, refusedToPerformReason } = (0, import_tool.toolsForLoop)(progress, context, toolDefinitions, { resultSchema, refuseToPerform: "allow" });
|
||||
const secrets = Object.fromEntries((context.agentParams.secrets || [])?.map((s) => [s.name, s.value]));
|
||||
const apiCacheTextBefore = context.agentParams.apiCacheFile ? await import_fs.default.promises.readFile(context.agentParams.apiCacheFile, "utf-8").catch(() => "{}") : "{}";
|
||||
const apiCacheBefore = JSON.parse(apiCacheTextBefore || "{}");
|
||||
const loop = new import_mcpBundle.Loop({
|
||||
api: context.agentParams.api,
|
||||
apiEndpoint: context.agentParams.apiEndpoint,
|
||||
apiKey: context.agentParams.apiKey,
|
||||
apiTimeout: context.agentParams.apiTimeout ?? 0,
|
||||
model: context.agentParams.model,
|
||||
maxTokens: params.maxTokens ?? context.maxTokensRemaining(),
|
||||
maxToolCalls: params.maxActions ?? context.agentParams.maxActions ?? 10,
|
||||
maxToolCallRetries: params.maxActionRetries ?? context.agentParams.maxActionRetries ?? 3,
|
||||
summarize: true,
|
||||
debug: import_utilsBundle.debug,
|
||||
callTool,
|
||||
tools,
|
||||
secrets,
|
||||
cache: apiCacheBefore,
|
||||
...context.events
|
||||
});
|
||||
const task = [];
|
||||
if (context.agentParams.systemPrompt) {
|
||||
task.push("### System");
|
||||
task.push(context.agentParams.systemPrompt);
|
||||
task.push("");
|
||||
}
|
||||
task.push("### Task");
|
||||
task.push(userTask);
|
||||
if (context.history().length) {
|
||||
task.push("### Context history");
|
||||
task.push(context.history().map((h) => `- ${h.type}: ${h.description}`).join("\n"));
|
||||
task.push("");
|
||||
}
|
||||
task.push("### Page snapshot");
|
||||
task.push(snapshot);
|
||||
task.push("");
|
||||
const { error, usage } = await loop.run(task.join("\n"), { signal: progress.signal });
|
||||
context.consumeTokens(usage.input + usage.output);
|
||||
if (context.agentParams.apiCacheFile) {
|
||||
const apiCacheAfter = { ...apiCacheBefore, ...loop.cache() };
|
||||
const sortedCache = Object.fromEntries(Object.entries(apiCacheAfter).sort(([a], [b]) => a.localeCompare(b)));
|
||||
const apiCacheTextAfter = JSON.stringify(sortedCache, void 0, 2);
|
||||
if (apiCacheTextAfter !== apiCacheTextBefore) {
|
||||
await import_fs.default.promises.mkdir(import_path.default.dirname(context.agentParams.apiCacheFile), { recursive: true });
|
||||
await import_fs.default.promises.writeFile(context.agentParams.apiCacheFile, apiCacheTextAfter);
|
||||
}
|
||||
}
|
||||
if (refusedToPerformReason())
|
||||
throw new Error(`Agent refused to perform action: ${refusedToPerformReason()}`);
|
||||
if (error)
|
||||
throw new Error(`Agentic loop failed: ${error}`);
|
||||
return { result: reportedResult ? reportedResult() : void 0 };
|
||||
}
|
||||
async function cachedPerform(progress, context, cacheKey) {
|
||||
if (!context.agentParams?.cacheFile)
|
||||
return;
|
||||
const cache = await cachedActions(context.agentParams?.cacheFile);
|
||||
const entry = cache.actions[cacheKey];
|
||||
if (!entry)
|
||||
return;
|
||||
for (const action of entry.actions)
|
||||
await (0, import_actionRunner.runAction)(progress, "run", context.page, action, context.agentParams.secrets ?? []);
|
||||
return entry.actions;
|
||||
}
|
||||
async function updateCache(context, cacheKey) {
|
||||
const cacheFile = context.agentParams?.cacheFile;
|
||||
const cacheOutFile = context.agentParams?.cacheOutFile;
|
||||
const cacheFileKey = cacheFile ?? cacheOutFile;
|
||||
const cache = cacheFileKey ? await cachedActions(cacheFileKey) : { actions: {}, newActions: {} };
|
||||
const newEntry = { actions: context.actions() };
|
||||
cache.actions[cacheKey] = newEntry;
|
||||
cache.newActions[cacheKey] = newEntry;
|
||||
if (cacheOutFile) {
|
||||
const entries = Object.entries(cache.newActions);
|
||||
entries.sort((e1, e2) => e1[0].localeCompare(e2[0]));
|
||||
await import_fs.default.promises.writeFile(cacheOutFile, JSON.stringify(Object.fromEntries(entries), void 0, 2));
|
||||
} else if (cacheFile) {
|
||||
const entries = Object.entries(cache.actions);
|
||||
entries.sort((e1, e2) => e1[0].localeCompare(e2[0]));
|
||||
await import_fs.default.promises.writeFile(cacheFile, JSON.stringify(Object.fromEntries(entries), void 0, 2));
|
||||
}
|
||||
}
|
||||
const allCaches = /* @__PURE__ */ new Map();
|
||||
async function cachedActions(cacheFile) {
|
||||
let cache = allCaches.get(cacheFile);
|
||||
if (!cache) {
|
||||
const content = await import_fs.default.promises.readFile(cacheFile, "utf-8").catch(() => "");
|
||||
let json;
|
||||
try {
|
||||
json = JSON.parse(content.trim() || "{}");
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to parse cache file ${cacheFile}:
|
||||
${error.message}`);
|
||||
}
|
||||
const parsed = actions.cachedActionsSchema.safeParse(json);
|
||||
if (parsed.error)
|
||||
throw new Error(`Failed to parse cache file ${cacheFile}:
|
||||
${import_mcpBundle.z.prettifyError(parsed.error)}`);
|
||||
cache = { actions: parsed.data, newActions: {} };
|
||||
allCaches.set(cacheFile, cache);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
pageAgentExpect,
|
||||
pageAgentExtract,
|
||||
pageAgentPerform
|
||||
});
|
||||
262
node_modules/playwright-core/lib/server/agent/performTools.js
generated
vendored
Normal file
262
node_modules/playwright-core/lib/server/agent/performTools.js
generated
vendored
Normal file
@@ -0,0 +1,262 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var performTools_exports = {};
|
||||
__export(performTools_exports, {
|
||||
default: () => performTools_default
|
||||
});
|
||||
module.exports = __toCommonJS(performTools_exports);
|
||||
var import_mcpBundle = require("../../mcpBundle");
|
||||
var import_tool = require("./tool");
|
||||
const navigateSchema = import_mcpBundle.z.object({
|
||||
url: import_mcpBundle.z.string().describe("URL to navigate to")
|
||||
});
|
||||
const navigate = (0, import_tool.defineTool)({
|
||||
schema: {
|
||||
name: "browser_navigate",
|
||||
title: "Navigate to URL",
|
||||
description: "Navigate to a URL",
|
||||
inputSchema: navigateSchema
|
||||
},
|
||||
handle: async (progress, context, params) => {
|
||||
return await context.runActionNoWait(progress, {
|
||||
method: "navigate",
|
||||
url: params.url
|
||||
});
|
||||
}
|
||||
});
|
||||
const snapshot = (0, import_tool.defineTool)({
|
||||
schema: {
|
||||
name: "browser_snapshot",
|
||||
title: "Page snapshot",
|
||||
description: "Capture accessibility snapshot of the current page, this is better than screenshot",
|
||||
inputSchema: import_mcpBundle.z.object({})
|
||||
},
|
||||
handle: async (progress, context, params) => {
|
||||
return await context.snapshotResult(progress);
|
||||
}
|
||||
});
|
||||
const elementSchema = import_mcpBundle.z.object({
|
||||
element: import_mcpBundle.z.string().describe("Human-readable element description used to obtain permission to interact with the element"),
|
||||
ref: import_mcpBundle.z.string().describe("Exact target element reference from the page snapshot")
|
||||
});
|
||||
const clickSchema = elementSchema.extend({
|
||||
doubleClick: import_mcpBundle.z.boolean().optional().describe("Whether to perform a double click instead of a single click"),
|
||||
button: import_mcpBundle.z.enum(["left", "right", "middle"]).optional().describe("Button to click, defaults to left"),
|
||||
modifiers: import_mcpBundle.z.array(import_mcpBundle.z.enum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"])).optional().describe("Modifier keys to press")
|
||||
});
|
||||
const click = (0, import_tool.defineTool)({
|
||||
schema: {
|
||||
name: "browser_click",
|
||||
title: "Click",
|
||||
description: "Perform click on a web page",
|
||||
inputSchema: clickSchema
|
||||
},
|
||||
handle: async (progress, context, params) => {
|
||||
const [selector] = await context.refSelectors(progress, [params]);
|
||||
return await context.runActionAndWait(progress, {
|
||||
method: "click",
|
||||
selector,
|
||||
button: params.button,
|
||||
modifiers: params.modifiers,
|
||||
clickCount: params.doubleClick ? 2 : void 0
|
||||
});
|
||||
}
|
||||
});
|
||||
const drag = (0, import_tool.defineTool)({
|
||||
schema: {
|
||||
name: "browser_drag",
|
||||
title: "Drag mouse",
|
||||
description: "Perform drag and drop between two elements",
|
||||
inputSchema: import_mcpBundle.z.object({
|
||||
startElement: import_mcpBundle.z.string().describe("Human-readable source element description used to obtain the permission to interact with the element"),
|
||||
startRef: import_mcpBundle.z.string().describe("Exact source element reference from the page snapshot"),
|
||||
endElement: import_mcpBundle.z.string().describe("Human-readable target element description used to obtain the permission to interact with the element"),
|
||||
endRef: import_mcpBundle.z.string().describe("Exact target element reference from the page snapshot")
|
||||
})
|
||||
},
|
||||
handle: async (progress, context, params) => {
|
||||
const [sourceSelector, targetSelector] = await context.refSelectors(progress, [
|
||||
{ ref: params.startRef, element: params.startElement },
|
||||
{ ref: params.endRef, element: params.endElement }
|
||||
]);
|
||||
return await context.runActionAndWait(progress, {
|
||||
method: "drag",
|
||||
sourceSelector,
|
||||
targetSelector
|
||||
});
|
||||
}
|
||||
});
|
||||
const hoverSchema = elementSchema.extend({
|
||||
modifiers: import_mcpBundle.z.array(import_mcpBundle.z.enum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"])).optional().describe("Modifier keys to press")
|
||||
});
|
||||
const hover = (0, import_tool.defineTool)({
|
||||
schema: {
|
||||
name: "browser_hover",
|
||||
title: "Hover mouse",
|
||||
description: "Hover over element on page",
|
||||
inputSchema: hoverSchema
|
||||
},
|
||||
handle: async (progress, context, params) => {
|
||||
const [selector] = await context.refSelectors(progress, [params]);
|
||||
return await context.runActionAndWait(progress, {
|
||||
method: "hover",
|
||||
selector,
|
||||
modifiers: params.modifiers
|
||||
});
|
||||
}
|
||||
});
|
||||
const selectOptionSchema = elementSchema.extend({
|
||||
values: import_mcpBundle.z.array(import_mcpBundle.z.string()).describe("Array of values to select in the dropdown. This can be a single value or multiple values.")
|
||||
});
|
||||
const selectOption = (0, import_tool.defineTool)({
|
||||
schema: {
|
||||
name: "browser_select_option",
|
||||
title: "Select option",
|
||||
description: "Select an option in a dropdown",
|
||||
inputSchema: selectOptionSchema
|
||||
},
|
||||
handle: async (progress, context, params) => {
|
||||
const [selector] = await context.refSelectors(progress, [params]);
|
||||
return await context.runActionAndWait(progress, {
|
||||
method: "selectOption",
|
||||
selector,
|
||||
labels: params.values
|
||||
});
|
||||
}
|
||||
});
|
||||
const pressKey = (0, import_tool.defineTool)({
|
||||
schema: {
|
||||
name: "browser_press_key",
|
||||
title: "Press a key",
|
||||
description: "Press a key on the keyboard",
|
||||
inputSchema: import_mcpBundle.z.object({
|
||||
key: import_mcpBundle.z.string().describe("Name of the key to press or a character to generate, such as `ArrowLeft` or `a`"),
|
||||
modifiers: import_mcpBundle.z.array(import_mcpBundle.z.enum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"])).optional().describe("Modifier keys to press")
|
||||
})
|
||||
},
|
||||
handle: async (progress, context, params) => {
|
||||
return await context.runActionAndWait(progress, {
|
||||
method: "pressKey",
|
||||
key: params.modifiers ? [...params.modifiers, params.key].join("+") : params.key
|
||||
});
|
||||
}
|
||||
});
|
||||
const typeSchema = elementSchema.extend({
|
||||
text: import_mcpBundle.z.string().describe("Text to type into the element"),
|
||||
submit: import_mcpBundle.z.boolean().optional().describe("Whether to submit entered text (press Enter after)"),
|
||||
slowly: import_mcpBundle.z.boolean().optional().describe("Whether to type one character at a time. Useful for triggering key handlers in the page. By default entire text is filled in at once.")
|
||||
});
|
||||
const type = (0, import_tool.defineTool)({
|
||||
schema: {
|
||||
name: "browser_type",
|
||||
title: "Type text",
|
||||
description: "Type text into editable element",
|
||||
inputSchema: typeSchema
|
||||
},
|
||||
handle: async (progress, context, params) => {
|
||||
const [selector] = await context.refSelectors(progress, [params]);
|
||||
if (params.slowly) {
|
||||
return await context.runActionAndWait(progress, {
|
||||
method: "pressSequentially",
|
||||
selector,
|
||||
text: params.text,
|
||||
submit: params.submit
|
||||
});
|
||||
} else {
|
||||
return await context.runActionAndWait(progress, {
|
||||
method: "fill",
|
||||
selector,
|
||||
text: params.text,
|
||||
submit: params.submit
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
const fillForm = (0, import_tool.defineTool)({
|
||||
schema: {
|
||||
name: "browser_fill_form",
|
||||
title: "Fill form",
|
||||
description: "Fill multiple form fields. Always use this tool when you can fill more than one field at a time.",
|
||||
inputSchema: import_mcpBundle.z.object({
|
||||
fields: import_mcpBundle.z.array(import_mcpBundle.z.object({
|
||||
name: import_mcpBundle.z.string().describe("Human-readable field name"),
|
||||
type: import_mcpBundle.z.enum(["textbox", "checkbox", "radio", "combobox", "slider"]).describe("Type of the field"),
|
||||
ref: import_mcpBundle.z.string().describe("Exact target field reference from the page snapshot"),
|
||||
value: import_mcpBundle.z.string().describe("Value to fill in the field. If the field is a checkbox, the value should be `true` or `false`. If the field is a combobox, the value should be the text of the option.")
|
||||
})).describe("Fields to fill in")
|
||||
})
|
||||
},
|
||||
handle: async (progress, context, params) => {
|
||||
const actions = [];
|
||||
for (const field of params.fields) {
|
||||
const [selector] = await context.refSelectors(progress, [{ ref: field.ref, element: field.name }]);
|
||||
if (field.type === "textbox" || field.type === "slider") {
|
||||
actions.push({
|
||||
method: "fill",
|
||||
selector,
|
||||
text: field.value
|
||||
});
|
||||
} else if (field.type === "checkbox" || field.type === "radio") {
|
||||
actions.push({
|
||||
method: "setChecked",
|
||||
selector,
|
||||
checked: field.value === "true"
|
||||
});
|
||||
} else if (field.type === "combobox") {
|
||||
actions.push({
|
||||
method: "selectOption",
|
||||
selector,
|
||||
labels: [field.value]
|
||||
});
|
||||
}
|
||||
}
|
||||
return await context.runActionsAndWait(progress, actions);
|
||||
}
|
||||
});
|
||||
const setCheckedSchema = elementSchema.extend({
|
||||
checked: import_mcpBundle.z.boolean().describe("Whether to check the checkbox")
|
||||
});
|
||||
const setChecked = (0, import_tool.defineTool)({
|
||||
schema: {
|
||||
name: "browser_set_checked",
|
||||
title: "Set checked",
|
||||
description: "Set the checked state of a checkbox",
|
||||
inputSchema: setCheckedSchema
|
||||
},
|
||||
handle: async (progress, context, params) => {
|
||||
const [selector] = await context.refSelectors(progress, [params]);
|
||||
return await context.runActionAndWait(progress, {
|
||||
method: "setChecked",
|
||||
selector,
|
||||
checked: params.checked
|
||||
});
|
||||
}
|
||||
});
|
||||
var performTools_default = [
|
||||
navigate,
|
||||
snapshot,
|
||||
click,
|
||||
drag,
|
||||
hover,
|
||||
selectOption,
|
||||
pressKey,
|
||||
type,
|
||||
fillForm,
|
||||
setChecked
|
||||
];
|
||||
109
node_modules/playwright-core/lib/server/agent/tool.js
generated
vendored
Normal file
109
node_modules/playwright-core/lib/server/agent/tool.js
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var tool_exports = {};
|
||||
__export(tool_exports, {
|
||||
defineTool: () => defineTool,
|
||||
toolsForLoop: () => toolsForLoop
|
||||
});
|
||||
module.exports = __toCommonJS(tool_exports);
|
||||
var import_mcpBundle = require("../../mcpBundle");
|
||||
var import_stringUtils = require("../../utils/isomorphic/stringUtils");
|
||||
function defineTool(tool) {
|
||||
return tool;
|
||||
}
|
||||
function toolsForLoop(progress, context, toolDefinitions, options = {}) {
|
||||
const tools = toolDefinitions.map((tool) => {
|
||||
const result = {
|
||||
name: tool.schema.name,
|
||||
description: tool.schema.description,
|
||||
inputSchema: import_mcpBundle.z.toJSONSchema(tool.schema.inputSchema)
|
||||
};
|
||||
return result;
|
||||
});
|
||||
if (options.resultSchema) {
|
||||
tools.push({
|
||||
name: "report_result",
|
||||
description: "Report the result of the task.",
|
||||
inputSchema: options.resultSchema
|
||||
});
|
||||
}
|
||||
if (options.refuseToPerform === "allow") {
|
||||
tools.push({
|
||||
name: "refuse_to_perform",
|
||||
description: "Refuse to perform action.",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
reason: {
|
||||
type: "string",
|
||||
description: `Call this when you believe that you can't perform the action because something is wrong with the page. The reason will be reported to the user.`
|
||||
}
|
||||
},
|
||||
required: ["reason"]
|
||||
}
|
||||
});
|
||||
}
|
||||
let reportedResult;
|
||||
let refusedToPerformReason;
|
||||
const callTool = async (params) => {
|
||||
if (params.name === "report_result") {
|
||||
reportedResult = params.arguments;
|
||||
return {
|
||||
content: [{ type: "text", text: "Done" }],
|
||||
isError: false
|
||||
};
|
||||
}
|
||||
if (params.name === "refuse_to_perform") {
|
||||
refusedToPerformReason = params.arguments.reason;
|
||||
return {
|
||||
content: [{ type: "text", text: "Done" }],
|
||||
isError: false
|
||||
};
|
||||
}
|
||||
const tool = toolDefinitions.find((t) => t.schema.name === params.name);
|
||||
if (!tool) {
|
||||
return {
|
||||
content: [{
|
||||
type: "text",
|
||||
text: `Tool ${params.name} not found. Available tools: ${toolDefinitions.map((t) => t.schema.name)}`
|
||||
}],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
try {
|
||||
return await tool.handle(progress, context, params.arguments);
|
||||
} catch (error) {
|
||||
return {
|
||||
content: [{ type: "text", text: (0, import_stringUtils.stripAnsiEscapes)(error.message) }],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
};
|
||||
return {
|
||||
tools,
|
||||
callTool,
|
||||
reportedResult: options.resultSchema ? () => reportedResult : void 0,
|
||||
refusedToPerformReason: () => refusedToPerformReason
|
||||
};
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
defineTool,
|
||||
toolsForLoop
|
||||
});
|
||||
2
node_modules/playwright-core/lib/server/artifact.js
generated
vendored
2
node_modules/playwright-core/lib/server/artifact.js
generated
vendored
@@ -103,7 +103,7 @@ class Artifact extends import_instrumentation.SdkObject {
|
||||
if (!this._unaccessibleErrorMessage)
|
||||
await import_fs.default.promises.unlink(this._localPath).catch((e) => {
|
||||
});
|
||||
await this.reportFinished(new import_errors.TargetClosedError());
|
||||
await this.reportFinished(new import_errors.TargetClosedError(this.closeReason()));
|
||||
}
|
||||
async reportFinished(error) {
|
||||
if (this._finished)
|
||||
|
||||
68
node_modules/playwright-core/lib/server/bidi/bidiBrowser.js
generated
vendored
68
node_modules/playwright-core/lib/server/bidi/bidiBrowser.js
generated
vendored
@@ -130,10 +130,13 @@ class BidiBrowser extends import_browser.Browser {
|
||||
const page2 = this._findPageForFrame(parentFrameId);
|
||||
if (page2) {
|
||||
page2._session.addFrameBrowsingContext(event.context);
|
||||
page2._page.frameManager.frameAttached(event.context, parentFrameId);
|
||||
const frame = page2._page.frameManager.frame(event.context);
|
||||
if (frame)
|
||||
frame._url = event.url;
|
||||
const frame = page2._page.frameManager.frameAttached(event.context, parentFrameId);
|
||||
frame._url = event.url;
|
||||
page2._getFrameNode(frame).then((node) => {
|
||||
const attributes = node?.value?.attributes;
|
||||
frame._name = attributes?.name ?? attributes?.id ?? "";
|
||||
});
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -142,6 +145,7 @@ class BidiBrowser extends import_browser.Browser {
|
||||
context = this._defaultContext;
|
||||
if (!context)
|
||||
return;
|
||||
context.doGrantGlobalPermissionsForURL(event.url);
|
||||
const session = this._connection.createMainFrameBrowsingContextSession(event.context);
|
||||
const opener = event.originalOpener && this._findPageForFrame(event.originalOpener);
|
||||
const page = new import_bidiPage.BidiPage(context, session, opener || null);
|
||||
@@ -217,6 +221,8 @@ class BidiBrowserContext extends import_browserContext.BrowserContext {
|
||||
}
|
||||
if (this._options.extraHTTPHeaders)
|
||||
promises.push(this.doUpdateExtraHTTPHeaders());
|
||||
if (this._options.permissions)
|
||||
promises.push(this.doGrantPermissions("*", this._options.permissions));
|
||||
await Promise.all(promises);
|
||||
}
|
||||
possiblyUninitializedPages() {
|
||||
@@ -275,17 +281,34 @@ class BidiBrowserContext extends import_browserContext.BrowserContext {
|
||||
);
|
||||
}
|
||||
async doGrantPermissions(origin, permissions) {
|
||||
if (origin === "null")
|
||||
return;
|
||||
const currentPermissions = this._originToPermissions.get(origin) || [];
|
||||
const toGrant = permissions.filter((permission) => !currentPermissions.includes(permission));
|
||||
this._originToPermissions.set(origin, [...currentPermissions, ...toGrant]);
|
||||
await Promise.all(toGrant.map((permission) => this._setPermission(origin, permission, bidi.Permissions.PermissionState.Granted)));
|
||||
if (origin === "*") {
|
||||
await Promise.all(this._bidiPages().flatMap(
|
||||
(page) => page._page.frames().map(
|
||||
(frame) => this.doGrantPermissions(new URL(frame._url).origin, permissions)
|
||||
)
|
||||
));
|
||||
} else {
|
||||
await Promise.all(toGrant.map((permission) => this._setPermission(origin, permission, bidi.Permissions.PermissionState.Granted)));
|
||||
}
|
||||
}
|
||||
async doGrantGlobalPermissionsForURL(url) {
|
||||
const permissions = this._originToPermissions.get("*");
|
||||
if (!permissions)
|
||||
return;
|
||||
await this.doGrantPermissions(new URL(url).origin, permissions);
|
||||
}
|
||||
async doClearPermissions() {
|
||||
const currentPermissions = [...this._originToPermissions.entries()];
|
||||
this._originToPermissions = /* @__PURE__ */ new Map();
|
||||
await Promise.all(currentPermissions.map(([origin, permissions]) => permissions.map(
|
||||
(p) => this._setPermission(origin, p, bidi.Permissions.PermissionState.Prompt)
|
||||
)));
|
||||
await Promise.all(currentPermissions.flatMap(([origin, permissions]) => {
|
||||
if (origin !== "*")
|
||||
return permissions.map((p) => this._setPermission(origin, p, bidi.Permissions.PermissionState.Prompt));
|
||||
}));
|
||||
}
|
||||
async _setPermission(origin, permission, state) {
|
||||
await this._browser._browserSession.send("permissions.setPermission", {
|
||||
@@ -349,21 +372,42 @@ class BidiBrowserContext extends import_browserContext.BrowserContext {
|
||||
await Promise.all(ids.map((script) => this._browser._browserSession.send("script.removePreloadScript", { script })));
|
||||
}
|
||||
async doUpdateRequestInterception() {
|
||||
if (this.requestInterceptors.length > 0 && !this._interceptId) {
|
||||
const { intercept } = await this._browser._browserSession.send("network.addIntercept", {
|
||||
phases: [bidi.Network.InterceptPhase.BeforeRequestSent],
|
||||
urlPatterns: [{ type: "pattern" }]
|
||||
});
|
||||
this._interceptId = intercept;
|
||||
}
|
||||
if (this.requestInterceptors.length === 0 && this._interceptId) {
|
||||
const intercept = this._interceptId;
|
||||
this._interceptId = void 0;
|
||||
await this._browser._browserSession.send("network.removeIntercept", { intercept });
|
||||
}
|
||||
}
|
||||
async doUpdateDefaultViewport() {
|
||||
if (!this._options.viewport)
|
||||
if (!this._options.viewport && !this._options.screen)
|
||||
return;
|
||||
const screenSize = this._options.screen || this._options.viewport;
|
||||
const viewportSize = this._options.viewport || this._options.screen;
|
||||
await Promise.all([
|
||||
this._browser._browserSession.send("browsingContext.setViewport", {
|
||||
viewport: {
|
||||
width: this._options.viewport.width,
|
||||
height: this._options.viewport.height
|
||||
width: viewportSize.width,
|
||||
height: viewportSize.height
|
||||
},
|
||||
devicePixelRatio: this._options.deviceScaleFactor || 1,
|
||||
userContexts: [this._userContextId()]
|
||||
}),
|
||||
this._browser._browserSession.send("emulation.setScreenOrientationOverride", {
|
||||
screenOrientation: getScreenOrientation(!!this._options.isMobile, this._options.viewport),
|
||||
screenOrientation: getScreenOrientation(!!this._options.isMobile, screenSize),
|
||||
userContexts: [this._userContextId()]
|
||||
}),
|
||||
this._browser._browserSession.send("emulation.setScreenSettingsOverride", {
|
||||
screenArea: {
|
||||
width: screenSize.width,
|
||||
height: screenSize.height
|
||||
},
|
||||
userContexts: [this._userContextId()]
|
||||
})
|
||||
]);
|
||||
|
||||
20
node_modules/playwright-core/lib/server/bidi/bidiChromium.js
generated
vendored
20
node_modules/playwright-core/lib/server/bidi/bidiChromium.js
generated
vendored
@@ -38,6 +38,7 @@ var import_bidiBrowser = require("./bidiBrowser");
|
||||
var import_bidiConnection = require("./bidiConnection");
|
||||
var import_chromiumSwitches = require("../chromium/chromiumSwitches");
|
||||
var import_chromium = require("../chromium/chromium");
|
||||
var import_hostPlatform = require("../utils/hostPlatform");
|
||||
class BidiChromium extends import_browserType.BrowserType {
|
||||
constructor(parent) {
|
||||
super(parent, "chromium");
|
||||
@@ -56,14 +57,12 @@ class BidiChromium extends import_browserType.BrowserType {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
doRewriteStartupLog(error) {
|
||||
if (!error.logs)
|
||||
return error;
|
||||
if (error.logs.includes("Missing X server"))
|
||||
error.logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
|
||||
if (!error.logs.includes("crbug.com/357670") && !error.logs.includes("No usable sandbox!") && !error.logs.includes("crbug.com/638180"))
|
||||
return error;
|
||||
error.logs = [
|
||||
doRewriteStartupLog(logs) {
|
||||
if (logs.includes("Missing X server"))
|
||||
logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
|
||||
if (!logs.includes("crbug.com/357670") && !logs.includes("No usable sandbox!") && !logs.includes("crbug.com/638180"))
|
||||
return logs;
|
||||
return [
|
||||
`Chromium sandboxing failed!`,
|
||||
`================================`,
|
||||
`To avoid the sandboxing issue, do either of the following:`,
|
||||
@@ -72,7 +71,6 @@ class BidiChromium extends import_browserType.BrowserType {
|
||||
`================================`,
|
||||
``
|
||||
].join("\n");
|
||||
return error;
|
||||
}
|
||||
amendEnvironment(env) {
|
||||
return env;
|
||||
@@ -109,11 +107,9 @@ class BidiChromium extends import_browserType.BrowserType {
|
||||
if (args.find((arg) => !arg.startsWith("-")))
|
||||
throw new Error("Arguments can not specify page to be opened");
|
||||
const chromeArguments = [...(0, import_chromiumSwitches.chromiumSwitches)(options.assistantMode)];
|
||||
if (import_os.default.platform() === "darwin") {
|
||||
if (import_os.default.platform() !== "darwin" || !(0, import_hostPlatform.hasGpuMac)()) {
|
||||
chromeArguments.push("--enable-unsafe-swiftshader");
|
||||
}
|
||||
if (options.devtools)
|
||||
chromeArguments.push("--auto-open-devtools-for-tabs");
|
||||
if (options.headless) {
|
||||
chromeArguments.push("--headless");
|
||||
chromeArguments.push(
|
||||
|
||||
1
node_modules/playwright-core/lib/server/bidi/bidiConnection.js
generated
vendored
1
node_modules/playwright-core/lib/server/bidi/bidiConnection.js
generated
vendored
@@ -173,6 +173,7 @@ class BidiSession extends import_events.EventEmitter {
|
||||
this._browsingContexts.clear();
|
||||
for (const callback of this._callbacks.values()) {
|
||||
callback.error.type = this._crashed ? "crashed" : "closed";
|
||||
callback.error.setMessage(`Internal server error, session ${callback.error.type}.`);
|
||||
callback.error.logs = this.connection._browserDisconnectedLogs;
|
||||
callback.reject(callback.error);
|
||||
}
|
||||
|
||||
116
node_modules/playwright-core/lib/server/bidi/bidiDeserializer.js
generated
vendored
Normal file
116
node_modules/playwright-core/lib/server/bidi/bidiDeserializer.js
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var bidiDeserializer_exports = {};
|
||||
__export(bidiDeserializer_exports, {
|
||||
deserializeBidiValue: () => deserializeBidiValue
|
||||
});
|
||||
module.exports = __toCommonJS(bidiDeserializer_exports);
|
||||
var import_javascript = require("../javascript");
|
||||
function deserializeBidiValue(result, internalIdMap = /* @__PURE__ */ new Map()) {
|
||||
switch (result.type) {
|
||||
case "undefined":
|
||||
return void 0;
|
||||
case "null":
|
||||
return null;
|
||||
case "number":
|
||||
return typeof result.value === "number" ? result.value : (0, import_javascript.parseUnserializableValue)(result.value);
|
||||
case "boolean":
|
||||
return Boolean(result.value);
|
||||
case "string":
|
||||
return result.value;
|
||||
case "bigint":
|
||||
return BigInt(result.value);
|
||||
case "array":
|
||||
return deserializeBidiList(result, internalIdMap);
|
||||
case "arraybuffer":
|
||||
return getValue(result, internalIdMap, () => ({}));
|
||||
case "date":
|
||||
return getValue(result, internalIdMap, () => new Date(result.value));
|
||||
case "error":
|
||||
return getValue(result, internalIdMap, () => {
|
||||
const error = new Error();
|
||||
error.stack = "";
|
||||
return error;
|
||||
});
|
||||
case "function":
|
||||
return void 0;
|
||||
case "generator":
|
||||
return getValue(result, internalIdMap, () => ({}));
|
||||
case "htmlcollection":
|
||||
return { ...deserializeBidiList(result, internalIdMap) };
|
||||
case "map":
|
||||
return getValue(result, internalIdMap, () => ({}));
|
||||
case "node":
|
||||
return "ref: <Node>";
|
||||
case "nodelist":
|
||||
return { ...deserializeBidiList(result, internalIdMap) };
|
||||
case "object":
|
||||
return deserializeBidiMapping(result, internalIdMap);
|
||||
case "promise":
|
||||
return getValue(result, internalIdMap, () => ({}));
|
||||
case "proxy":
|
||||
return getValue(result, internalIdMap, () => ({}));
|
||||
case "regexp":
|
||||
return getValue(result, internalIdMap, () => new RegExp(result.value.pattern, result.value.flags));
|
||||
case "set":
|
||||
return getValue(result, internalIdMap, () => ({}));
|
||||
case "symbol":
|
||||
return void 0;
|
||||
case "typedarray":
|
||||
return void 0;
|
||||
case "weakmap":
|
||||
return getValue(result, internalIdMap, () => ({}));
|
||||
case "weakset":
|
||||
return getValue(result, internalIdMap, () => ({}));
|
||||
case "window":
|
||||
return "ref: <Window>";
|
||||
}
|
||||
}
|
||||
function getValue(bidiValue, internalIdMap, defaultValue) {
|
||||
if ("internalId" in bidiValue && bidiValue.internalId) {
|
||||
if (internalIdMap.has(bidiValue.internalId)) {
|
||||
return internalIdMap.get(bidiValue.internalId);
|
||||
} else {
|
||||
const value = defaultValue();
|
||||
internalIdMap.set(bidiValue.internalId, value);
|
||||
return value;
|
||||
}
|
||||
} else {
|
||||
return defaultValue();
|
||||
}
|
||||
}
|
||||
function deserializeBidiList(bidiValue, internalIdMap) {
|
||||
const result = getValue(bidiValue, internalIdMap, () => []);
|
||||
for (const val of bidiValue.value || [])
|
||||
result.push(deserializeBidiValue(val, internalIdMap));
|
||||
return result;
|
||||
}
|
||||
function deserializeBidiMapping(bidiValue, internalIdMap) {
|
||||
const result = getValue(bidiValue, internalIdMap, () => ({}));
|
||||
for (const [serializedKey, serializedValue] of bidiValue.value || []) {
|
||||
const key = typeof serializedKey === "string" ? serializedKey : deserializeBidiValue(serializedKey, internalIdMap);
|
||||
const value = deserializeBidiValue(serializedValue, internalIdMap);
|
||||
result[key] = value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
deserializeBidiValue
|
||||
});
|
||||
104
node_modules/playwright-core/lib/server/bidi/bidiExecutionContext.js
generated
vendored
104
node_modules/playwright-core/lib/server/bidi/bidiExecutionContext.js
generated
vendored
@@ -36,9 +36,9 @@ var import_utils = require("../../utils");
|
||||
var import_utilityScriptSerializers = require("../../utils/isomorphic/utilityScriptSerializers");
|
||||
var js = __toESM(require("../javascript"));
|
||||
var dom = __toESM(require("../dom"));
|
||||
var import_bidiDeserializer = require("./third_party/bidiDeserializer");
|
||||
var bidi = __toESM(require("./third_party/bidiProtocol"));
|
||||
var import_bidiSerializer = require("./third_party/bidiSerializer");
|
||||
var import_bidiDeserializer = require("./bidiDeserializer");
|
||||
class BidiExecutionContext {
|
||||
constructor(session, realmInfo) {
|
||||
this._session = session;
|
||||
@@ -65,7 +65,7 @@ class BidiExecutionContext {
|
||||
userActivation: true
|
||||
});
|
||||
if (response.type === "success")
|
||||
return import_bidiDeserializer.BidiDeserializer.deserialize(response.result);
|
||||
return (0, import_bidiDeserializer.deserializeBidiValue)(response.result);
|
||||
if (response.type === "exception")
|
||||
throw new js.JavaScriptErrorInEvaluate(response.exceptionDetails.text);
|
||||
throw new js.JavaScriptErrorInEvaluate("Unexpected response type: " + JSON.stringify(response));
|
||||
@@ -108,7 +108,7 @@ class BidiExecutionContext {
|
||||
throw new js.JavaScriptErrorInEvaluate(response.exceptionDetails.text);
|
||||
if (response.type === "success") {
|
||||
if (returnByValue)
|
||||
return (0, import_utilityScriptSerializers.parseEvaluationResultValue)(import_bidiDeserializer.BidiDeserializer.deserialize(response.result));
|
||||
return (0, import_utilityScriptSerializers.parseEvaluationResultValue)((0, import_bidiDeserializer.deserializeBidiValue)(response.result));
|
||||
return createHandle(utilityScript._context, response.result);
|
||||
}
|
||||
throw new js.JavaScriptErrorInEvaluate("Unexpected response type: " + JSON.stringify(response));
|
||||
@@ -123,7 +123,10 @@ class BidiExecutionContext {
|
||||
}
|
||||
return names2;
|
||||
});
|
||||
const values = await Promise.all(names.map((name) => handle.evaluateHandle((object, name2) => object[name2], name)));
|
||||
const values = await Promise.all(names.map(async (name) => {
|
||||
const value = await this._rawCallFunction("(object, name) => object[name]", [{ handle: handle._objectId }, { type: "string", value: name }], true, false);
|
||||
return createHandle(handle._context, value);
|
||||
}));
|
||||
const map = /* @__PURE__ */ new Map();
|
||||
for (let i = 0; i < names.length; i++)
|
||||
map.set(names[i], values[i]);
|
||||
@@ -152,7 +155,7 @@ class BidiExecutionContext {
|
||||
return createHandle(context, result);
|
||||
}
|
||||
async contentFrameIdForFrame(handle) {
|
||||
const contentWindow = await this._rawCallFunction("e => e.contentWindow", { handle: handle._objectId });
|
||||
const contentWindow = await this._rawCallFunction("e => e.contentWindow", [{ handle: handle._objectId }]);
|
||||
if (contentWindow?.type === "window")
|
||||
return contentWindow.value.context;
|
||||
return null;
|
||||
@@ -166,17 +169,17 @@ class BidiExecutionContext {
|
||||
return null;
|
||||
}
|
||||
async _remoteValueForReference(reference, createHandle2) {
|
||||
return await this._rawCallFunction("e => e", reference, createHandle2);
|
||||
return await this._rawCallFunction("e => e", [reference], createHandle2);
|
||||
}
|
||||
async _rawCallFunction(functionDeclaration, arg, createHandle2) {
|
||||
async _rawCallFunction(functionDeclaration, args, createHandle2, awaitPromise = true) {
|
||||
const response = await this._session.send("script.callFunction", {
|
||||
functionDeclaration,
|
||||
target: this._target,
|
||||
arguments: [arg],
|
||||
arguments: args,
|
||||
// "Root" is necessary for the handle to be returned.
|
||||
resultOwnership: createHandle2 ? bidi.Script.ResultOwnership.Root : bidi.Script.ResultOwnership.None,
|
||||
serializationOptions: { maxObjectDepth: 0, maxDomDepth: 0 },
|
||||
awaitPromise: true,
|
||||
awaitPromise,
|
||||
userActivation: true
|
||||
});
|
||||
if (response.type === "exception")
|
||||
@@ -186,25 +189,65 @@ class BidiExecutionContext {
|
||||
throw new js.JavaScriptErrorInEvaluate("Unexpected response type: " + JSON.stringify(response));
|
||||
}
|
||||
}
|
||||
function renderPreview(remoteObject) {
|
||||
if (remoteObject.type === "undefined")
|
||||
return "undefined";
|
||||
if (remoteObject.type === "null")
|
||||
return "null";
|
||||
if ("value" in remoteObject)
|
||||
return String(remoteObject.value);
|
||||
return `<${remoteObject.type}>`;
|
||||
}
|
||||
function remoteObjectValue(remoteObject) {
|
||||
if (remoteObject.type === "undefined")
|
||||
return void 0;
|
||||
if (remoteObject.type === "null")
|
||||
return null;
|
||||
if (remoteObject.type === "number" && typeof remoteObject.value === "string")
|
||||
return js.parseUnserializableValue(remoteObject.value);
|
||||
if ("value" in remoteObject)
|
||||
return remoteObject.value;
|
||||
return void 0;
|
||||
function renderPreview(remoteObject, nested = false) {
|
||||
switch (remoteObject.type) {
|
||||
case "undefined":
|
||||
case "null":
|
||||
return remoteObject.type;
|
||||
case "number":
|
||||
case "boolean":
|
||||
case "string":
|
||||
return String(remoteObject.value);
|
||||
case "bigint":
|
||||
return `${remoteObject.value}n`;
|
||||
case "date":
|
||||
return String(new Date(remoteObject.value));
|
||||
case "regexp":
|
||||
return String(new RegExp(remoteObject.value.pattern, remoteObject.value.flags));
|
||||
case "node":
|
||||
return remoteObject.value?.localName || "Node";
|
||||
case "object":
|
||||
if (nested)
|
||||
return "Object";
|
||||
const tokens = [];
|
||||
for (const [name, value] of remoteObject.value || []) {
|
||||
if (typeof name === "string")
|
||||
tokens.push(`${name}: ${renderPreview(value, true)}`);
|
||||
}
|
||||
return `{${tokens.join(", ")}}`;
|
||||
case "array":
|
||||
case "htmlcollection":
|
||||
case "nodelist":
|
||||
if (nested || !remoteObject.value)
|
||||
return remoteObject.value ? `Array(${remoteObject.value.length})` : "Array";
|
||||
return `[${remoteObject.value.map((v) => renderPreview(v, true)).join(", ")}]`;
|
||||
case "map":
|
||||
return remoteObject.value ? `Map(${remoteObject.value.length})` : "Map";
|
||||
case "set":
|
||||
return remoteObject.value ? `Set(${remoteObject.value.length})` : "Set";
|
||||
case "arraybuffer":
|
||||
return "ArrayBuffer";
|
||||
case "error":
|
||||
return "Error";
|
||||
case "function":
|
||||
return "Function";
|
||||
case "generator":
|
||||
return "Generator";
|
||||
case "promise":
|
||||
return "Promise";
|
||||
case "proxy":
|
||||
return "Proxy";
|
||||
case "symbol":
|
||||
return "Symbol()";
|
||||
case "typedarray":
|
||||
return "TypedArray";
|
||||
case "weakmap":
|
||||
return "WeakMap";
|
||||
case "weakset":
|
||||
return "WeakSet";
|
||||
case "window":
|
||||
return "Window";
|
||||
}
|
||||
}
|
||||
function createHandle(context, remoteObject) {
|
||||
if (remoteObject.type === "node") {
|
||||
@@ -212,7 +255,10 @@ function createHandle(context, remoteObject) {
|
||||
return new dom.ElementHandle(context, remoteObject.handle);
|
||||
}
|
||||
const objectId = "handle" in remoteObject ? remoteObject.handle : void 0;
|
||||
return new js.JSHandle(context, remoteObject.type, renderPreview(remoteObject), objectId, remoteObjectValue(remoteObject));
|
||||
const preview = renderPreview(remoteObject);
|
||||
const handle = new js.JSHandle(context, remoteObject.type, preview, objectId, (0, import_bidiDeserializer.deserializeBidiValue)(remoteObject));
|
||||
handle._setPreview(preview);
|
||||
return handle;
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
|
||||
14
node_modules/playwright-core/lib/server/bidi/bidiFirefox.js
generated
vendored
14
node_modules/playwright-core/lib/server/bidi/bidiFirefox.js
generated
vendored
@@ -49,15 +49,13 @@ class BidiFirefox extends import_browserType.BrowserType {
|
||||
async connectToTransport(transport, options) {
|
||||
return import_bidiBrowser.BidiBrowser.connect(this.attribution.playwright, transport, options);
|
||||
}
|
||||
doRewriteStartupLog(error) {
|
||||
if (!error.logs)
|
||||
return error;
|
||||
if (error.logs.includes(`as root in a regular user's session is not supported.`))
|
||||
error.logs = "\n" + (0, import_ascii.wrapInASCIIBox)(`Firefox is unable to launch if the $HOME folder isn't owned by the current user.
|
||||
doRewriteStartupLog(logs) {
|
||||
if (logs.includes(`as root in a regular user's session is not supported.`))
|
||||
logs = "\n" + (0, import_ascii.wrapInASCIIBox)(`Firefox is unable to launch if the $HOME folder isn't owned by the current user.
|
||||
Workaround: Set the HOME=/root environment variable${process.env.GITHUB_ACTION ? " in your GitHub Actions workflow file" : ""} when running Playwright.`, 1);
|
||||
if (error.logs.includes("no DISPLAY environment variable specified"))
|
||||
error.logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
|
||||
return error;
|
||||
if (logs.includes("no DISPLAY environment variable specified"))
|
||||
logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
|
||||
return logs;
|
||||
}
|
||||
amendEnvironment(env) {
|
||||
if (!import_path.default.isAbsolute(import_os.default.homedir()))
|
||||
|
||||
2
node_modules/playwright-core/lib/server/bidi/bidiNetworkManager.js
generated
vendored
2
node_modules/playwright-core/lib/server/bidi/bidiNetworkManager.js
generated
vendored
@@ -342,7 +342,7 @@ function resourceTypeFromBidi(requestDestination, requestInitiatorType, eventIni
|
||||
case "image":
|
||||
return "image";
|
||||
case "object":
|
||||
return "object";
|
||||
return "other";
|
||||
case "paintworklet":
|
||||
return "script";
|
||||
case "script":
|
||||
|
||||
67
node_modules/playwright-core/lib/server/bidi/bidiPage.js
generated
vendored
67
node_modules/playwright-core/lib/server/bidi/bidiPage.js
generated
vendored
@@ -32,6 +32,7 @@ __export(bidiPage_exports, {
|
||||
kPlaywrightBindingChannel: () => kPlaywrightBindingChannel
|
||||
});
|
||||
module.exports = __toCommonJS(bidiPage_exports);
|
||||
var import_debugLogger = require("../utils/debugLogger");
|
||||
var import_eventsHelper = require("../utils/eventsHelper");
|
||||
var dialog = __toESM(require("../dialog"));
|
||||
var dom = __toESM(require("../dom"));
|
||||
@@ -87,8 +88,7 @@ class BidiPage {
|
||||
async _initialize() {
|
||||
this._onFrameAttached(this._session.sessionId, null);
|
||||
await Promise.all([
|
||||
this.updateHttpCredentials(),
|
||||
this.updateRequestInterception()
|
||||
this.updateHttpCredentials()
|
||||
// If the page is created by the Playwright client's call, some initialization
|
||||
// may be pending. Wait for it to complete before reporting the page as new.
|
||||
]);
|
||||
@@ -179,10 +179,12 @@ class BidiPage {
|
||||
}
|
||||
_onNavigationCommitted(params) {
|
||||
const frameId = params.context;
|
||||
const frame = this._page.frameManager.frame(frameId);
|
||||
this._browserContext.doGrantGlobalPermissionsForURL(params.url).catch((error) => import_debugLogger.debugLogger.log("error", error));
|
||||
this._page.frameManager.frameCommittedNewDocumentNavigation(
|
||||
frameId,
|
||||
params.url,
|
||||
"",
|
||||
frame._name,
|
||||
params.navigation,
|
||||
/* initial */
|
||||
false
|
||||
@@ -263,7 +265,7 @@ ${params.stackTrace?.callFrames.map((f) => {
|
||||
return;
|
||||
const callFrame = params.stackTrace?.callFrames[0];
|
||||
const location = callFrame ?? { url: "", lineNumber: 1, columnNumber: 1 };
|
||||
this._page.addConsoleMessage(null, entry.method, entry.args.map((arg) => (0, import_bidiExecutionContext.createHandle)(context, arg)), location, params.text || void 0);
|
||||
this._page.addConsoleMessage(null, entry.method, entry.args.map((arg) => (0, import_bidiExecutionContext.createHandle)(context, arg)), location);
|
||||
}
|
||||
async _onFileDialogOpened(params) {
|
||||
if (!params.element)
|
||||
@@ -272,8 +274,11 @@ ${params.stackTrace?.callFrames.map((f) => {
|
||||
if (!frame)
|
||||
return;
|
||||
const executionContext = await frame._mainContext();
|
||||
const handle = await toBidiExecutionContext(executionContext).remoteObjectForNodeId(executionContext, { sharedId: params.element.sharedId });
|
||||
await this._page._onFileChooserOpened(handle);
|
||||
try {
|
||||
const handle = await toBidiExecutionContext(executionContext).remoteObjectForNodeId(executionContext, { sharedId: params.element.sharedId });
|
||||
await this._page._onFileChooserOpened(handle);
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
async navigateFrame(frame, url, referrer) {
|
||||
const { navigation } = await this._session.send("browsingContext.navigate", {
|
||||
@@ -306,6 +311,7 @@ ${params.stackTrace?.callFrames.map((f) => {
|
||||
const emulatedSize = this._page.emulatedSize();
|
||||
if (!emulatedSize)
|
||||
return;
|
||||
const screenSize = emulatedSize.screen;
|
||||
const viewportSize = emulatedSize.viewport;
|
||||
await Promise.all([
|
||||
this._session.send("browsingContext.setViewport", {
|
||||
@@ -318,12 +324,19 @@ ${params.stackTrace?.callFrames.map((f) => {
|
||||
}),
|
||||
this._session.send("emulation.setScreenOrientationOverride", {
|
||||
contexts: [this._session.sessionId],
|
||||
screenOrientation: (0, import_bidiBrowser.getScreenOrientation)(!!options.isMobile, viewportSize)
|
||||
screenOrientation: (0, import_bidiBrowser.getScreenOrientation)(!!options.isMobile, screenSize)
|
||||
}),
|
||||
this._session.send("emulation.setScreenSettingsOverride", {
|
||||
contexts: [this._session.sessionId],
|
||||
screenArea: {
|
||||
width: screenSize.width,
|
||||
height: screenSize.height
|
||||
}
|
||||
})
|
||||
]);
|
||||
}
|
||||
async updateRequestInterception() {
|
||||
await this._networkManager.setRequestInterception(this._page.needsRequestInterception());
|
||||
await this._networkManager.setRequestInterception(this._page.requestInterceptors.length > 0);
|
||||
}
|
||||
async updateOffline() {
|
||||
}
|
||||
@@ -482,7 +495,9 @@ ${params.stackTrace?.callFrames.map((f) => {
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
async setScreencastOptions(options) {
|
||||
async startScreencast(options) {
|
||||
}
|
||||
async stopScreencast() {
|
||||
}
|
||||
rafCountForStablePosition() {
|
||||
return 1;
|
||||
@@ -537,26 +552,22 @@ ${params.stackTrace?.callFrames.map((f) => {
|
||||
const parent = frame.parentFrame();
|
||||
if (!parent)
|
||||
throw new Error("Frame has been detached.");
|
||||
const parentContext = await parent._mainContext();
|
||||
const list = await parentContext.evaluateHandle(() => {
|
||||
return [...document.querySelectorAll("iframe,frame")];
|
||||
});
|
||||
const length = await list.evaluate((list2) => list2.length);
|
||||
let foundElement = null;
|
||||
for (let i = 0; i < length; i++) {
|
||||
const element = await list.evaluateHandle((list2, i2) => list2[i2], i);
|
||||
const candidate = await element.contentFrame();
|
||||
if (frame === candidate) {
|
||||
foundElement = element;
|
||||
break;
|
||||
} else {
|
||||
element.dispose();
|
||||
}
|
||||
}
|
||||
list.dispose();
|
||||
if (!foundElement)
|
||||
const node = await this._getFrameNode(frame);
|
||||
if (!node?.sharedId)
|
||||
throw new Error("Frame has been detached.");
|
||||
return foundElement;
|
||||
const parentFrameExecutionContext = await parent._mainContext();
|
||||
return await toBidiExecutionContext(parentFrameExecutionContext).remoteObjectForNodeId(parentFrameExecutionContext, { sharedId: node.sharedId });
|
||||
}
|
||||
async _getFrameNode(frame) {
|
||||
const parent = frame.parentFrame();
|
||||
if (!parent)
|
||||
return void 0;
|
||||
const result = await this._session.send("browsingContext.locateNodes", {
|
||||
context: parent._id,
|
||||
locator: { type: "context", value: { context: frame._id } }
|
||||
});
|
||||
const node = result.nodes[0];
|
||||
return node;
|
||||
}
|
||||
shouldToggleStyleSheetToSyncAnimations() {
|
||||
return true;
|
||||
|
||||
98
node_modules/playwright-core/lib/server/bidi/third_party/bidiDeserializer.js
generated
vendored
98
node_modules/playwright-core/lib/server/bidi/third_party/bidiDeserializer.js
generated
vendored
@@ -1,98 +0,0 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var bidiDeserializer_exports = {};
|
||||
__export(bidiDeserializer_exports, {
|
||||
BidiDeserializer: () => BidiDeserializer
|
||||
});
|
||||
module.exports = __toCommonJS(bidiDeserializer_exports);
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2024 Google Inc.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
class BidiDeserializer {
|
||||
static deserialize(result) {
|
||||
if (!result)
|
||||
return void 0;
|
||||
switch (result.type) {
|
||||
case "array":
|
||||
return result.value?.map((value) => {
|
||||
return BidiDeserializer.deserialize(value);
|
||||
});
|
||||
case "set":
|
||||
return result.value?.reduce((acc, value) => {
|
||||
return acc.add(BidiDeserializer.deserialize(value));
|
||||
}, /* @__PURE__ */ new Set());
|
||||
case "object":
|
||||
return result.value?.reduce((acc, tuple) => {
|
||||
const { key, value } = BidiDeserializer._deserializeTuple(tuple);
|
||||
acc[key] = value;
|
||||
return acc;
|
||||
}, {});
|
||||
case "map":
|
||||
return result.value?.reduce((acc, tuple) => {
|
||||
const { key, value } = BidiDeserializer._deserializeTuple(tuple);
|
||||
return acc.set(key, value);
|
||||
}, /* @__PURE__ */ new Map());
|
||||
case "promise":
|
||||
return {};
|
||||
case "regexp":
|
||||
return new RegExp(result.value.pattern, result.value.flags);
|
||||
case "date":
|
||||
return new Date(result.value);
|
||||
case "undefined":
|
||||
return void 0;
|
||||
case "null":
|
||||
return null;
|
||||
case "number":
|
||||
return BidiDeserializer._deserializeNumber(result.value);
|
||||
case "bigint":
|
||||
return BigInt(result.value);
|
||||
case "boolean":
|
||||
return Boolean(result.value);
|
||||
case "string":
|
||||
return result.value;
|
||||
}
|
||||
throw new Error(`Deserialization of type ${result.type} not supported.`);
|
||||
}
|
||||
static _deserializeNumber(value) {
|
||||
switch (value) {
|
||||
case "-0":
|
||||
return -0;
|
||||
case "NaN":
|
||||
return NaN;
|
||||
case "Infinity":
|
||||
return Infinity;
|
||||
case "-Infinity":
|
||||
return -Infinity;
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
static _deserializeTuple([serializedKey, serializedValue]) {
|
||||
const key = typeof serializedKey === "string" ? serializedKey : BidiDeserializer.deserialize(serializedKey);
|
||||
const value = BidiDeserializer.deserialize(serializedValue);
|
||||
return { key, value };
|
||||
}
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
BidiDeserializer
|
||||
});
|
||||
1
node_modules/playwright-core/lib/server/bidi/third_party/bidiProtocolCore.js
generated
vendored
1
node_modules/playwright-core/lib/server/bidi/third_party/bidiProtocolCore.js
generated
vendored
@@ -128,6 +128,7 @@ var Network;
|
||||
((Network2) => {
|
||||
let DataType;
|
||||
((DataType2) => {
|
||||
DataType2["Request"] = "request";
|
||||
DataType2["Response"] = "response";
|
||||
})(DataType = Network2.DataType || (Network2.DataType = {}));
|
||||
})(Network || (Network = {}));
|
||||
|
||||
57
node_modules/playwright-core/lib/server/browserContext.js
generated
vendored
57
node_modules/playwright-core/lib/server/browserContext.js
generated
vendored
@@ -55,6 +55,24 @@ var import_recorderApp = require("./recorder/recorderApp");
|
||||
var import_selectors = require("./selectors");
|
||||
var import_tracing = require("./trace/recorder/tracing");
|
||||
var rawStorageSource = __toESM(require("../generated/storageScriptSource"));
|
||||
const BrowserContextEvent = {
|
||||
Console: "console",
|
||||
Close: "close",
|
||||
Page: "page",
|
||||
// Can't use just 'error' due to node.js special treatment of error events.
|
||||
// @see https://nodejs.org/api/events.html#events_error_events
|
||||
PageError: "pageerror",
|
||||
Request: "request",
|
||||
Response: "response",
|
||||
RequestFailed: "requestfailed",
|
||||
RequestFinished: "requestfinished",
|
||||
RequestAborted: "requestaborted",
|
||||
RequestFulfilled: "requestfulfilled",
|
||||
RequestContinued: "requestcontinued",
|
||||
BeforeClose: "beforeclose",
|
||||
VideoStarted: "videostarted",
|
||||
RecorderEvent: "recorderevent"
|
||||
};
|
||||
class BrowserContext extends import_instrumentation.SdkObject {
|
||||
constructor(browser, options, browserContextId) {
|
||||
super(browser, "browser-context");
|
||||
@@ -69,6 +87,7 @@ class BrowserContext extends import_instrumentation.SdkObject {
|
||||
this._creatingStorageStatePage = false;
|
||||
this.initScripts = [];
|
||||
this._routesInFlight = /* @__PURE__ */ new Set();
|
||||
this._consoleApiExposed = false;
|
||||
this.attribution.context = this;
|
||||
this._browser = browser;
|
||||
this._options = options;
|
||||
@@ -82,24 +101,7 @@ class BrowserContext extends import_instrumentation.SdkObject {
|
||||
this.dialogManager = new import_dialog.DialogManager(this.instrumentation);
|
||||
}
|
||||
static {
|
||||
this.Events = {
|
||||
Console: "console",
|
||||
Close: "close",
|
||||
Page: "page",
|
||||
// Can't use just 'error' due to node.js special treatment of error events.
|
||||
// @see https://nodejs.org/api/events.html#events_error_events
|
||||
PageError: "pageerror",
|
||||
Request: "request",
|
||||
Response: "response",
|
||||
RequestFailed: "requestfailed",
|
||||
RequestFinished: "requestfinished",
|
||||
RequestAborted: "requestaborted",
|
||||
RequestFulfilled: "requestfulfilled",
|
||||
RequestContinued: "requestcontinued",
|
||||
BeforeClose: "beforeclose",
|
||||
VideoStarted: "videostarted",
|
||||
RecorderEvent: "recorderevent"
|
||||
};
|
||||
this.Events = BrowserContextEvent;
|
||||
}
|
||||
isPersistentContext() {
|
||||
return this._isPersistentContext;
|
||||
@@ -119,12 +121,8 @@ class BrowserContext extends import_instrumentation.SdkObject {
|
||||
if (this._debugger.isPaused())
|
||||
import_recorderApp.RecorderApp.showInspectorNoReply(this);
|
||||
});
|
||||
if ((0, import_debug.debugMode)() === "console") {
|
||||
await this.extendInjectedScript(`
|
||||
function installConsoleApi(injectedScript) { injectedScript.consoleApi.install(); }
|
||||
module.exports = { default: () => installConsoleApi };
|
||||
`);
|
||||
}
|
||||
if ((0, import_debug.debugMode)() === "console")
|
||||
await this.exposeConsoleApi();
|
||||
if (this._options.serviceWorkers === "block")
|
||||
await this.addInitScript(void 0, `
|
||||
if (navigator.serviceWorker) navigator.serviceWorker.register = async () => { console.warn('Service Worker registration blocked by Playwright'); };
|
||||
@@ -135,6 +133,15 @@ if (navigator.serviceWorker) navigator.serviceWorker.register = async () => { co
|
||||
debugger() {
|
||||
return this._debugger;
|
||||
}
|
||||
async exposeConsoleApi() {
|
||||
if (this._consoleApiExposed)
|
||||
return;
|
||||
this._consoleApiExposed = true;
|
||||
await this.extendInjectedScript(`
|
||||
function installConsoleApi(injectedScript) { injectedScript.consoleApi.install(); }
|
||||
module.exports = { default: () => installConsoleApi };
|
||||
`);
|
||||
}
|
||||
async _ensureVideosPath() {
|
||||
if (this._options.recordVideo)
|
||||
await (0, import_fileUtils.mkdirIfNeeded)(import_path.default.join(this._options.recordVideo.dir, "dummy"));
|
||||
@@ -322,7 +329,7 @@ if (navigator.serviceWorker) navigator.serviceWorker.register = async () => { co
|
||||
const pageOrError = await progress.race(page.waitForInitializedOrError());
|
||||
if (pageOrError instanceof Error)
|
||||
throw pageOrError;
|
||||
await page.mainFrame()._waitForLoadState(progress, "load");
|
||||
await page.mainFrame().waitForLoadState(progress, "load");
|
||||
return page;
|
||||
}
|
||||
async _loadDefaultContext(progress) {
|
||||
|
||||
16
node_modules/playwright-core/lib/server/browserType.js
generated
vendored
16
node_modules/playwright-core/lib/server/browserType.js
generated
vendored
@@ -250,6 +250,13 @@ class BrowserType extends import_instrumentation.SdkObject {
|
||||
this.waitForReadyState(options, browserLogsCollector),
|
||||
exitPromise.then(() => ({ wsEndpoint: void 0 }))
|
||||
]);
|
||||
if (exitPromise.isDone()) {
|
||||
const log = import_helper.helper.formatBrowserLogs(browserLogsCollector.recentLogs());
|
||||
const updatedLog = this.doRewriteStartupLog(log);
|
||||
throw new Error(`Failed to launch the browser process.
|
||||
Browser logs:
|
||||
${updatedLog}`);
|
||||
}
|
||||
if (options.cdpPort !== void 0 || !this.supportsPipeTransport()) {
|
||||
transport = await import_transport.WebSocketTransport.connect(progress, wsEndpoint);
|
||||
} else {
|
||||
@@ -276,15 +283,14 @@ class BrowserType extends import_instrumentation.SdkObject {
|
||||
throw new Error("Connecting to SELENIUM_REMOTE_URL is only supported by Chromium");
|
||||
}
|
||||
_validateLaunchOptions(options) {
|
||||
const { devtools = false } = options;
|
||||
let { headless = !devtools, downloadsPath, proxy } = options;
|
||||
let { headless = true, downloadsPath, proxy } = options;
|
||||
if ((0, import_debug.debugMode)() === "inspector")
|
||||
headless = false;
|
||||
if (downloadsPath && !import_path.default.isAbsolute(downloadsPath))
|
||||
downloadsPath = import_path.default.join(process.cwd(), downloadsPath);
|
||||
if (options.socksProxyPort)
|
||||
proxy = { server: `socks5://127.0.0.1:${options.socksProxyPort}` };
|
||||
return { ...options, devtools, headless, downloadsPath, proxy };
|
||||
return { ...options, headless, downloadsPath, proxy };
|
||||
}
|
||||
_createUserDataDirArgMisuseError(userDataDirArg) {
|
||||
switch (this.attribution.playwright.options.sdkLanguage) {
|
||||
@@ -301,7 +307,9 @@ class BrowserType extends import_instrumentation.SdkObject {
|
||||
_rewriteStartupLog(error) {
|
||||
if (!(0, import_protocolError.isProtocolError)(error))
|
||||
return error;
|
||||
return this.doRewriteStartupLog(error);
|
||||
if (error.logs)
|
||||
error.logs = this.doRewriteStartupLog(error.logs);
|
||||
return error;
|
||||
}
|
||||
async waitForReadyState(options, browserLogsCollector) {
|
||||
return {};
|
||||
|
||||
33
node_modules/playwright-core/lib/server/chromium/chromium.js
generated
vendored
33
node_modules/playwright-core/lib/server/chromium/chromium.js
generated
vendored
@@ -114,7 +114,8 @@ class Chromium extends import_browserType.BrowserType {
|
||||
};
|
||||
(0, import_browserContext.validateBrowserContextOptions)(persistent, browserOptions);
|
||||
const browser = await progress.race(import_crBrowser.CRBrowser.connect(this.attribution.playwright, chromeTransport, browserOptions));
|
||||
browser._isCollocatedWithServer = false;
|
||||
if (!options.isLocal)
|
||||
browser._isCollocatedWithServer = false;
|
||||
browser.on(import_browser.Browser.Events.Disconnected, doCleanup);
|
||||
return browser;
|
||||
} catch (error) {
|
||||
@@ -128,13 +129,8 @@ class Chromium extends import_browserType.BrowserType {
|
||||
return directory ? new import_crDevTools.CRDevTools(import_path.default.join(directory, "devtools-preferences.json")) : void 0;
|
||||
}
|
||||
async connectToTransport(transport, options, browserLogsCollector) {
|
||||
let devtools = this._devtools;
|
||||
if (options.__testHookForDevTools) {
|
||||
devtools = this._createDevTools();
|
||||
await options.__testHookForDevTools(devtools);
|
||||
}
|
||||
try {
|
||||
return await import_crBrowser.CRBrowser.connect(this.attribution.playwright, transport, options, devtools);
|
||||
return await import_crBrowser.CRBrowser.connect(this.attribution.playwright, transport, options, this._devtools);
|
||||
} catch (e) {
|
||||
if (browserLogsCollector.recentLogs().some((log) => log.includes("Failed to create a ProcessSingleton for your profile directory."))) {
|
||||
throw new Error(
|
||||
@@ -144,14 +140,12 @@ class Chromium extends import_browserType.BrowserType {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
doRewriteStartupLog(error) {
|
||||
if (!error.logs)
|
||||
return error;
|
||||
if (error.logs.includes("Missing X server"))
|
||||
error.logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
|
||||
if (!error.logs.includes("crbug.com/357670") && !error.logs.includes("No usable sandbox!") && !error.logs.includes("crbug.com/638180"))
|
||||
return error;
|
||||
error.logs = [
|
||||
doRewriteStartupLog(logs) {
|
||||
if (logs.includes("Missing X server"))
|
||||
logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
|
||||
if (!logs.includes("crbug.com/357670") && !logs.includes("No usable sandbox!") && !logs.includes("crbug.com/638180"))
|
||||
return logs;
|
||||
return [
|
||||
`Chromium sandboxing failed!`,
|
||||
`================================`,
|
||||
`To avoid the sandboxing issue, do either of the following:`,
|
||||
@@ -160,7 +154,6 @@ class Chromium extends import_browserType.BrowserType {
|
||||
`================================`,
|
||||
``
|
||||
].join("\n");
|
||||
return error;
|
||||
}
|
||||
amendEnvironment(env) {
|
||||
return env;
|
||||
@@ -284,11 +277,9 @@ class Chromium extends import_browserType.BrowserType {
|
||||
if (args.find((arg) => !arg.startsWith("-")))
|
||||
throw new Error("Arguments can not specify page to be opened");
|
||||
const chromeArguments = [...(0, import_chromiumSwitches.chromiumSwitches)(options.assistantMode, options.channel)];
|
||||
if (import_os.default.platform() === "darwin") {
|
||||
if (import_os.default.platform() !== "darwin" || !(0, import_utils.hasGpuMac)()) {
|
||||
chromeArguments.push("--enable-unsafe-swiftshader");
|
||||
}
|
||||
if (options.devtools)
|
||||
chromeArguments.push("--auto-open-devtools-for-tabs");
|
||||
if (options.headless) {
|
||||
chromeArguments.push("--headless");
|
||||
chromeArguments.push(
|
||||
@@ -324,6 +315,10 @@ class Chromium extends import_browserType.BrowserType {
|
||||
return waitForReadyState(options, browserLogsCollector);
|
||||
}
|
||||
getExecutableName(options) {
|
||||
if (options.channel && import_registry.registry.isChromiumAlias(options.channel))
|
||||
return "chromium";
|
||||
if (options.channel === "chromium-tip-of-tree")
|
||||
return options.headless ? "chromium-tip-of-tree-headless-shell" : "chromium-tip-of-tree";
|
||||
if (options.channel)
|
||||
return options.channel;
|
||||
return options.headless ? "chromium-headless-shell" : "chromium";
|
||||
|
||||
4
node_modules/playwright-core/lib/server/chromium/chromiumSwitches.js
generated
vendored
4
node_modules/playwright-core/lib/server/chromium/chromiumSwitches.js
generated
vendored
@@ -22,10 +22,10 @@ __export(chromiumSwitches_exports, {
|
||||
});
|
||||
module.exports = __toCommonJS(chromiumSwitches_exports);
|
||||
const disabledFeatures = (assistantMode) => [
|
||||
// See https://github.com/microsoft/playwright/pull/10380
|
||||
"AcceptCHFrame",
|
||||
// See https://github.com/microsoft/playwright/issues/14047
|
||||
"AvoidUnnecessaryBeforeUnloadCheckSync",
|
||||
// See https://github.com/microsoft/playwright/issues/38568
|
||||
"BoundaryEventDispatchTracksNodeRemoval",
|
||||
"DestroyProfileOnBrowserClose",
|
||||
// See https://github.com/microsoft/playwright/pull/13854
|
||||
"DialMediaRouteProvider",
|
||||
|
||||
34
node_modules/playwright-core/lib/server/chromium/crBrowser.js
generated
vendored
34
node_modules/playwright-core/lib/server/chromium/crBrowser.js
generated
vendored
@@ -284,11 +284,12 @@ class CRBrowser extends import_browser.Browser {
|
||||
return this._clientRootSessionPromise;
|
||||
}
|
||||
}
|
||||
const CREvents = {
|
||||
ServiceWorker: "serviceworker"
|
||||
};
|
||||
class CRBrowserContext extends import_browserContext.BrowserContext {
|
||||
static {
|
||||
this.CREvents = {
|
||||
ServiceWorker: "serviceworker"
|
||||
};
|
||||
this.CREvents = CREvents;
|
||||
}
|
||||
constructor(browser, browserContextId, options) {
|
||||
super(browser, options, browserContextId);
|
||||
@@ -388,15 +389,24 @@ class CRBrowserContext extends import_browserContext.BrowserContext {
|
||||
["midi-sysex", "midiSysex"],
|
||||
["storage-access", "storageAccess"],
|
||||
["local-fonts", "localFonts"],
|
||||
["local-network-access", "localNetworkAccess"]
|
||||
["local-network-access", ["localNetworkAccess", "localNetwork", "loopbackNetwork"]]
|
||||
]);
|
||||
const filtered = permissions.map((permission) => {
|
||||
const protocolPermission = webPermissionToProtocol.get(permission);
|
||||
if (!protocolPermission)
|
||||
throw new Error("Unknown permission: " + permission);
|
||||
return protocolPermission;
|
||||
});
|
||||
await this._browser._session.send("Browser.grantPermissions", { origin: origin === "*" ? void 0 : origin, browserContextId: this._browserContextId, permissions: filtered });
|
||||
const grantPermissions = async (mapping) => {
|
||||
const filtered = permissions.flatMap((permission) => {
|
||||
const protocolPermission = mapping.get(permission);
|
||||
if (!protocolPermission)
|
||||
throw new Error("Unknown permission: " + permission);
|
||||
return typeof protocolPermission === "string" ? [protocolPermission] : protocolPermission;
|
||||
});
|
||||
await this._browser._session.send("Browser.grantPermissions", { origin: origin === "*" ? void 0 : origin, browserContextId: this._browserContextId, permissions: filtered });
|
||||
};
|
||||
try {
|
||||
await grantPermissions(webPermissionToProtocol);
|
||||
} catch (e) {
|
||||
const fallbackMapping = new Map(webPermissionToProtocol);
|
||||
fallbackMapping.set("local-network-access", ["localNetworkAccess"]);
|
||||
await grantPermissions(fallbackMapping);
|
||||
}
|
||||
}
|
||||
async doClearPermissions() {
|
||||
await this._browser._session.send("Browser.resetPermissions", { browserContextId: this._browserContextId });
|
||||
@@ -470,7 +480,7 @@ class CRBrowserContext extends import_browserContext.BrowserContext {
|
||||
}
|
||||
}
|
||||
async stopVideoRecording() {
|
||||
await Promise.all(this._crPages().map((crPage) => crPage._mainFrameSession._stopVideoRecording()));
|
||||
await Promise.all(this._crPages().map((crPage) => crPage._page.screencast.stopVideoRecording()));
|
||||
}
|
||||
onClosePersistent() {
|
||||
}
|
||||
|
||||
5
node_modules/playwright-core/lib/server/chromium/crConnection.js
generated
vendored
5
node_modules/playwright-core/lib/server/chromium/crConnection.js
generated
vendored
@@ -94,11 +94,6 @@ class CRSession extends import_instrumentation.SdkObject {
|
||||
this._parentSession = parentSession;
|
||||
this._sessionId = sessionId;
|
||||
this._eventListener = eventListener;
|
||||
this.on = super.on;
|
||||
this.addListener = super.addListener;
|
||||
this.off = super.removeListener;
|
||||
this.removeListener = super.removeListener;
|
||||
this.once = super.once;
|
||||
}
|
||||
_markAsCrashed() {
|
||||
this._crashed = true;
|
||||
|
||||
2
node_modules/playwright-core/lib/server/chromium/crDevTools.js
generated
vendored
2
node_modules/playwright-core/lib/server/chromium/crDevTools.js
generated
vendored
@@ -44,8 +44,6 @@ class CRDevTools {
|
||||
return;
|
||||
const parsed = JSON.parse(event.payload);
|
||||
let result = void 0;
|
||||
if (this.__testHookOnBinding)
|
||||
this.__testHookOnBinding(parsed);
|
||||
if (parsed.method === "getPreferences") {
|
||||
if (this._prefs === void 0) {
|
||||
try {
|
||||
|
||||
45
node_modules/playwright-core/lib/server/chromium/crNetworkManager.js
generated
vendored
45
node_modules/playwright-core/lib/server/chromium/crNetworkManager.js
generated
vendored
@@ -296,6 +296,10 @@ class CRNetworkManager {
|
||||
if (requestPausedEvent) {
|
||||
if (redirectedFrom || !this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled) {
|
||||
headersOverride = redirectedFrom?._originalRequestRoute?._alreadyContinuedParams?.headers;
|
||||
if (headersOverride) {
|
||||
const originalHeaders = Object.entries(requestPausedEvent.request.headers).map(([name, value]) => ({ name, value }));
|
||||
headersOverride = network.applyHeadersOverrides(originalHeaders, headersOverride);
|
||||
}
|
||||
requestPausedSessionInfo.session._sendMayFail("Fetch.continueRequest", { requestId: requestPausedEvent.requestId, headers: headersOverride });
|
||||
} else {
|
||||
route = new RouteImpl(requestPausedSessionInfo.session, requestPausedEvent.requestId);
|
||||
@@ -482,12 +486,11 @@ class InterceptableRequest {
|
||||
url,
|
||||
postDataEntries = null
|
||||
} = requestPausedEvent ? requestPausedEvent.request : requestWillBeSentEvent.request;
|
||||
const type = (requestWillBeSentEvent.type || "").toLowerCase();
|
||||
let postDataBuffer = null;
|
||||
const entries = postDataEntries?.filter((entry) => entry.bytes);
|
||||
if (entries && entries.length)
|
||||
postDataBuffer = Buffer.concat(entries.map((entry) => Buffer.from(entry.bytes, "base64")));
|
||||
this.request = new network.Request(context, frame, serviceWorker, redirectedFrom?.request || null, documentId, url, type, method, postDataBuffer, headersOverride || (0, import_utils.headersObjectToArray)(headers));
|
||||
this.request = new network.Request(context, frame, serviceWorker, redirectedFrom?.request || null, documentId, url, toResourceType(requestWillBeSentEvent.type || "Other"), method, postDataBuffer, headersOverride || (0, import_utils.headersObjectToArray)(headers));
|
||||
}
|
||||
}
|
||||
class RouteImpl {
|
||||
@@ -660,6 +663,44 @@ class ResponseExtraInfoTracker {
|
||||
this._requests.delete(requestId);
|
||||
}
|
||||
}
|
||||
function toResourceType(type) {
|
||||
switch (type) {
|
||||
case "Document":
|
||||
return "document";
|
||||
case "Stylesheet":
|
||||
return "stylesheet";
|
||||
case "Image":
|
||||
return "image";
|
||||
case "Media":
|
||||
return "media";
|
||||
case "Font":
|
||||
return "font";
|
||||
case "Script":
|
||||
return "script";
|
||||
case "TextTrack":
|
||||
return "texttrack";
|
||||
case "XHR":
|
||||
return "xhr";
|
||||
case "Fetch":
|
||||
return "fetch";
|
||||
case "EventSource":
|
||||
return "eventsource";
|
||||
case "WebSocket":
|
||||
return "websocket";
|
||||
case "Manifest":
|
||||
return "manifest";
|
||||
case "Ping":
|
||||
return "ping";
|
||||
case "CSPViolationReport":
|
||||
return "cspreport";
|
||||
case "Prefetch":
|
||||
case "SignedExchange":
|
||||
case "Preflight":
|
||||
case "FedCM":
|
||||
default:
|
||||
return "other";
|
||||
}
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
CRNetworkManager
|
||||
|
||||
106
node_modules/playwright-core/lib/server/chromium/crPage.js
generated
vendored
106
node_modules/playwright-core/lib/server/chromium/crPage.js
generated
vendored
@@ -31,9 +31,7 @@ __export(crPage_exports, {
|
||||
CRPage: () => CRPage
|
||||
});
|
||||
module.exports = __toCommonJS(crPage_exports);
|
||||
var import_path = __toESM(require("path"));
|
||||
var import_assert = require("../../utils/isomorphic/assert");
|
||||
var import_crypto = require("../utils/crypto");
|
||||
var import_eventsHelper = require("../utils/eventsHelper");
|
||||
var import_stackTrace = require("../../utils/isomorphic/stackTrace");
|
||||
var dialog = __toESM(require("../dialog"));
|
||||
@@ -42,7 +40,6 @@ var frames = __toESM(require("../frames"));
|
||||
var import_helper = require("../helper");
|
||||
var network = __toESM(require("../network"));
|
||||
var import_page = require("../page");
|
||||
var import_registry = require("../registry");
|
||||
var import_crCoverage = require("./crCoverage");
|
||||
var import_crDragDrop = require("./crDragDrop");
|
||||
var import_crExecutionContext = require("./crExecutionContext");
|
||||
@@ -51,7 +48,6 @@ var import_crNetworkManager = require("./crNetworkManager");
|
||||
var import_crPdf = require("./crPdf");
|
||||
var import_crProtocolHelper = require("./crProtocolHelper");
|
||||
var import_defaultFontFamilies = require("./defaultFontFamilies");
|
||||
var import_videoRecorder = require("./videoRecorder");
|
||||
var import_errors = require("../errors");
|
||||
var import_protocolError = require("../protocolError");
|
||||
class CRPage {
|
||||
@@ -236,17 +232,16 @@ class CRPage {
|
||||
async scrollRectIntoViewIfNeeded(handle, rect) {
|
||||
return this._sessionForHandle(handle)._scrollRectIntoViewIfNeeded(handle, rect);
|
||||
}
|
||||
async setScreencastOptions(options) {
|
||||
if (options) {
|
||||
await this._mainFrameSession._startScreencast(this, {
|
||||
format: "jpeg",
|
||||
quality: options.quality,
|
||||
maxWidth: options.width,
|
||||
maxHeight: options.height
|
||||
});
|
||||
} else {
|
||||
await this._mainFrameSession._stopScreencast(this);
|
||||
}
|
||||
async startScreencast(options) {
|
||||
await this._mainFrameSession._client.send("Page.startScreencast", {
|
||||
format: "jpeg",
|
||||
quality: options.quality,
|
||||
maxWidth: options.width,
|
||||
maxHeight: options.height
|
||||
});
|
||||
}
|
||||
async stopScreencast() {
|
||||
await this._mainFrameSession._client._sendMayFail("Page.stopScreencast");
|
||||
}
|
||||
rafCountForStablePosition() {
|
||||
return 1;
|
||||
@@ -311,9 +306,6 @@ class FrameSession {
|
||||
// Marks the oopif session that remote -> local transition has happened in the parent.
|
||||
// See Target.detachedFromTarget handler for details.
|
||||
this._swappedIn = false;
|
||||
this._videoRecorder = null;
|
||||
this._screencastId = null;
|
||||
this._screencastClients = /* @__PURE__ */ new Set();
|
||||
this._workerSessions = /* @__PURE__ */ new Map();
|
||||
this._initScriptIds = /* @__PURE__ */ new Map();
|
||||
this._client = client;
|
||||
@@ -365,23 +357,9 @@ class FrameSession {
|
||||
const { windowId } = await this._client.send("Browser.getWindowForTarget");
|
||||
this._windowId = windowId;
|
||||
}
|
||||
let screencastOptions;
|
||||
if (!this._page.isStorageStatePage && this._isMainFrame() && this._crPage._browserContext._options.recordVideo && hasUIWindow) {
|
||||
const screencastId = (0, import_crypto.createGuid)();
|
||||
const outputFile = import_path.default.join(this._crPage._browserContext._options.recordVideo.dir, screencastId + ".webm");
|
||||
screencastOptions = {
|
||||
// validateBrowserContextOptions ensures correct video size.
|
||||
...this._crPage._browserContext._options.recordVideo.size,
|
||||
outputFile
|
||||
};
|
||||
await this._crPage._browserContext._ensureVideosPath();
|
||||
await this._createVideoRecorder(screencastId, screencastOptions);
|
||||
this._crPage._page.waitForInitializedOrError().then((p) => {
|
||||
if (p instanceof Error)
|
||||
this._stopVideoRecording().catch(() => {
|
||||
});
|
||||
});
|
||||
}
|
||||
let videoOptions;
|
||||
if (!this._page.isStorageStatePage && this._isMainFrame() && hasUIWindow)
|
||||
videoOptions = this._crPage._page.screencast.launchVideoRecorder();
|
||||
let lifecycleEventsEnabled;
|
||||
if (!this._isMainFrame())
|
||||
this._addRendererListeners();
|
||||
@@ -461,15 +439,15 @@ class FrameSession {
|
||||
true
|
||||
/* runImmediately */
|
||||
));
|
||||
if (screencastOptions)
|
||||
promises.push(this._startVideoRecording(screencastOptions));
|
||||
if (videoOptions)
|
||||
promises.push(this._crPage._page.screencast.startVideoRecording(videoOptions));
|
||||
}
|
||||
promises.push(this._client.send("Runtime.runIfWaitingForDebugger"));
|
||||
promises.push(this._firstNonInitialNavigationCommittedPromise);
|
||||
await Promise.all(promises);
|
||||
}
|
||||
dispose() {
|
||||
this._firstNonInitialNavigationCommittedReject(new import_errors.TargetClosedError());
|
||||
this._firstNonInitialNavigationCommittedReject(new import_errors.TargetClosedError(this._page.closeReason()));
|
||||
for (const childSession of this._childSessions)
|
||||
childSession.dispose();
|
||||
if (this._parentSession)
|
||||
@@ -730,63 +708,17 @@ class FrameSession {
|
||||
}
|
||||
}
|
||||
_onScreencastFrame(payload) {
|
||||
this._page.throttleScreencastFrameAck(() => {
|
||||
this._client.send("Page.screencastFrameAck", { sessionId: payload.sessionId }).catch(() => {
|
||||
});
|
||||
this._page.screencast.throttleFrameAck(() => {
|
||||
this._client._sendMayFail("Page.screencastFrameAck", { sessionId: payload.sessionId });
|
||||
});
|
||||
const buffer = Buffer.from(payload.data, "base64");
|
||||
this._page.emit(import_page.Page.Events.ScreencastFrame, {
|
||||
buffer,
|
||||
frameSwapWallTime: payload.metadata.timestamp ? payload.metadata.timestamp * 1e3 : void 0,
|
||||
frameSwapWallTime: payload.metadata.timestamp ? payload.metadata.timestamp * 1e3 : Date.now(),
|
||||
width: payload.metadata.deviceWidth,
|
||||
height: payload.metadata.deviceHeight
|
||||
});
|
||||
}
|
||||
async _createVideoRecorder(screencastId, options) {
|
||||
(0, import_assert.assert)(!this._screencastId);
|
||||
const ffmpegPath = import_registry.registry.findExecutable("ffmpeg").executablePathOrDie(this._page.browserContext._browser.sdkLanguage());
|
||||
this._videoRecorder = await import_videoRecorder.VideoRecorder.launch(this._crPage._page, ffmpegPath, options);
|
||||
this._screencastId = screencastId;
|
||||
}
|
||||
async _startVideoRecording(options) {
|
||||
const screencastId = this._screencastId;
|
||||
(0, import_assert.assert)(screencastId);
|
||||
this._page.once(import_page.Page.Events.Close, () => this._stopVideoRecording().catch(() => {
|
||||
}));
|
||||
const gotFirstFrame = new Promise((f) => this._client.once("Page.screencastFrame", f));
|
||||
await this._startScreencast(this._videoRecorder, {
|
||||
format: "jpeg",
|
||||
quality: 90,
|
||||
maxWidth: options.width,
|
||||
maxHeight: options.height
|
||||
});
|
||||
gotFirstFrame.then(() => {
|
||||
this._crPage._browserContext._browser._videoStarted(this._crPage._browserContext, screencastId, options.outputFile, this._crPage._page.waitForInitializedOrError());
|
||||
});
|
||||
}
|
||||
async _stopVideoRecording() {
|
||||
if (!this._screencastId)
|
||||
return;
|
||||
const screencastId = this._screencastId;
|
||||
this._screencastId = null;
|
||||
const recorder = this._videoRecorder;
|
||||
this._videoRecorder = null;
|
||||
await this._stopScreencast(recorder);
|
||||
await recorder.stop().catch(() => {
|
||||
});
|
||||
const video = this._crPage._browserContext._browser._takeVideo(screencastId);
|
||||
video?.reportFinished();
|
||||
}
|
||||
async _startScreencast(client, options = {}) {
|
||||
this._screencastClients.add(client);
|
||||
if (this._screencastClients.size === 1)
|
||||
await this._client.send("Page.startScreencast", options);
|
||||
}
|
||||
async _stopScreencast(client) {
|
||||
this._screencastClients.delete(client);
|
||||
if (!this._screencastClients.size)
|
||||
await this._client._sendMayFail("Page.stopScreencast");
|
||||
}
|
||||
async _updateGeolocation(initial) {
|
||||
const geolocation = this._crPage._browserContext._options.geolocation;
|
||||
if (!initial || geolocation)
|
||||
|
||||
35
node_modules/playwright-core/lib/server/codegen/javascript.js
generated
vendored
35
node_modules/playwright-core/lib/server/codegen/javascript.js
generated
vendored
@@ -90,7 +90,7 @@ class JavaScriptLanguageGenerator {
|
||||
case "fill":
|
||||
return `await ${subject}.${this._asLocator(action.selector)}.fill(${quote(action.text)});`;
|
||||
case "setInputFiles":
|
||||
return `await ${subject}.${this._asLocator(action.selector)}.setInputFiles(${formatObject(action.files.length === 1 ? action.files[0] : action.files)});`;
|
||||
return `await ${subject}.${this._asLocator(action.selector)}.setInputFiles(${(0, import_utils.formatObject)(action.files.length === 1 ? action.files[0] : action.files)});`;
|
||||
case "press": {
|
||||
const modifiers = (0, import_language.toKeyboardModifiers)(action.modifiers);
|
||||
const shortcut = [...modifiers, action.key].join("+");
|
||||
@@ -99,7 +99,7 @@ class JavaScriptLanguageGenerator {
|
||||
case "navigate":
|
||||
return `await ${subject}.goto(${quote(action.url)});`;
|
||||
case "select":
|
||||
return `await ${subject}.${this._asLocator(action.selector)}.selectOption(${formatObject(action.options.length === 1 ? action.options[0] : action.options)});`;
|
||||
return `await ${subject}.${this._asLocator(action.selector)}.selectOption(${(0, import_utils.formatObject)(action.options.length === 1 ? action.options[0] : action.options)});`;
|
||||
case "assertText":
|
||||
return `${this._isTest ? "" : "// "}await expect(${subject}.${this._asLocator(action.selector)}).${action.substring ? "toContainText" : "toHaveText"}(${quote(action.text)});`;
|
||||
case "assertChecked":
|
||||
@@ -151,7 +151,7 @@ ${useText ? "\ntest.use(" + useText + ");\n" : ""}
|
||||
const { ${options.browserName}${options.deviceName ? ", devices" : ""} } = require('playwright');
|
||||
|
||||
(async () => {
|
||||
const browser = await ${options.browserName}.launch(${formatObjectOrVoid(options.launchOptions)});
|
||||
const browser = await ${options.browserName}.launch(${(0, import_utils.formatObjectOrVoid)(options.launchOptions)});
|
||||
const context = await browser.newContext(${formatContextOptions(options.contextOptions, options.deviceName, false)});`);
|
||||
if (options.contextOptions.recordHar)
|
||||
formatter.add(` await context.routeFromHAR(${quote(options.contextOptions.recordHar.path)});`);
|
||||
@@ -171,37 +171,14 @@ function formatOptions(value, hasArguments) {
|
||||
const keys = Object.keys(value).filter((key) => value[key] !== void 0);
|
||||
if (!keys.length)
|
||||
return "";
|
||||
return (hasArguments ? ", " : "") + formatObject(value);
|
||||
}
|
||||
function formatObject(value, indent = " ") {
|
||||
if (typeof value === "string")
|
||||
return quote(value);
|
||||
if (Array.isArray(value))
|
||||
return `[${value.map((o) => formatObject(o)).join(", ")}]`;
|
||||
if (typeof value === "object") {
|
||||
const keys = Object.keys(value).filter((key) => value[key] !== void 0).sort();
|
||||
if (!keys.length)
|
||||
return "{}";
|
||||
const tokens = [];
|
||||
for (const key of keys)
|
||||
tokens.push(`${key}: ${formatObject(value[key])}`);
|
||||
return `{
|
||||
${indent}${tokens.join(`,
|
||||
${indent}`)}
|
||||
}`;
|
||||
}
|
||||
return String(value);
|
||||
}
|
||||
function formatObjectOrVoid(value, indent = " ") {
|
||||
const result = formatObject(value, indent);
|
||||
return result === "{}" ? "" : result;
|
||||
return (hasArguments ? ", " : "") + (0, import_utils.formatObject)(value);
|
||||
}
|
||||
function formatContextOptions(options, deviceName, isTest) {
|
||||
const device = deviceName && import_deviceDescriptors.deviceDescriptors[deviceName];
|
||||
options = { ...options, recordHar: void 0 };
|
||||
if (!device)
|
||||
return formatObjectOrVoid(options);
|
||||
let serializedObject = formatObjectOrVoid((0, import_language.sanitizeDeviceOptions)(device, options));
|
||||
return (0, import_utils.formatObjectOrVoid)(options);
|
||||
let serializedObject = (0, import_utils.formatObjectOrVoid)((0, import_language.sanitizeDeviceOptions)(device, options));
|
||||
if (!serializedObject)
|
||||
serializedObject = "{\n}";
|
||||
const lines = serializedObject.split("\n");
|
||||
|
||||
112
node_modules/playwright-core/lib/server/deviceDescriptorsSource.json
generated
vendored
112
node_modules/playwright-core/lib/server/deviceDescriptorsSource.json
generated
vendored
@@ -110,7 +110,7 @@
|
||||
"defaultBrowserType": "webkit"
|
||||
},
|
||||
"Galaxy S5": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 360,
|
||||
"height": 640
|
||||
@@ -121,7 +121,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy S5 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 640,
|
||||
"height": 360
|
||||
@@ -132,7 +132,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy S8": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 360,
|
||||
"height": 740
|
||||
@@ -143,7 +143,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy S8 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 740,
|
||||
"height": 360
|
||||
@@ -154,7 +154,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy S9+": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 320,
|
||||
"height": 658
|
||||
@@ -165,7 +165,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy S9+ landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 658,
|
||||
"height": 320
|
||||
@@ -176,7 +176,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy S24": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; SM-S921U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; SM-S921U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 360,
|
||||
"height": 780
|
||||
@@ -187,7 +187,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy S24 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; SM-S921U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; SM-S921U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 780,
|
||||
"height": 360
|
||||
@@ -198,7 +198,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy A55": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; SM-A556B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; SM-A556B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 480,
|
||||
"height": 1040
|
||||
@@ -209,7 +209,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy A55 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; SM-A556B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; SM-A556B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 1040,
|
||||
"height": 480
|
||||
@@ -220,7 +220,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy Tab S4": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 712,
|
||||
"height": 1138
|
||||
@@ -231,7 +231,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy Tab S4 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 1138,
|
||||
"height": 712
|
||||
@@ -242,7 +242,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy Tab S9": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; SM-X710) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; SM-X710) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 640,
|
||||
"height": 1024
|
||||
@@ -253,7 +253,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy Tab S9 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; SM-X710) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; SM-X710) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 1024,
|
||||
"height": 640
|
||||
@@ -1208,7 +1208,7 @@
|
||||
"defaultBrowserType": "webkit"
|
||||
},
|
||||
"LG Optimus L70": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 384,
|
||||
"height": 640
|
||||
@@ -1219,7 +1219,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"LG Optimus L70 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 640,
|
||||
"height": 384
|
||||
@@ -1230,7 +1230,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Microsoft Lumia 550": {
|
||||
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36 Edge/14.14263",
|
||||
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36 Edge/14.14263",
|
||||
"viewport": {
|
||||
"width": 360,
|
||||
"height": 640
|
||||
@@ -1241,7 +1241,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Microsoft Lumia 550 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36 Edge/14.14263",
|
||||
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36 Edge/14.14263",
|
||||
"viewport": {
|
||||
"width": 640,
|
||||
"height": 360
|
||||
@@ -1252,7 +1252,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Microsoft Lumia 950": {
|
||||
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36 Edge/14.14263",
|
||||
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36 Edge/14.14263",
|
||||
"viewport": {
|
||||
"width": 360,
|
||||
"height": 640
|
||||
@@ -1263,7 +1263,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Microsoft Lumia 950 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36 Edge/14.14263",
|
||||
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36 Edge/14.14263",
|
||||
"viewport": {
|
||||
"width": 640,
|
||||
"height": 360
|
||||
@@ -1274,7 +1274,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 10": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 800,
|
||||
"height": 1280
|
||||
@@ -1285,7 +1285,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 10 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 1280,
|
||||
"height": 800
|
||||
@@ -1296,7 +1296,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 4": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 384,
|
||||
"height": 640
|
||||
@@ -1307,7 +1307,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 4 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 640,
|
||||
"height": 384
|
||||
@@ -1318,7 +1318,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 5": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 360,
|
||||
"height": 640
|
||||
@@ -1329,7 +1329,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 5 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 640,
|
||||
"height": 360
|
||||
@@ -1340,7 +1340,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 5X": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 412,
|
||||
"height": 732
|
||||
@@ -1351,7 +1351,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 5X landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 732,
|
||||
"height": 412
|
||||
@@ -1362,7 +1362,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 6": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 412,
|
||||
"height": 732
|
||||
@@ -1373,7 +1373,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 6 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 732,
|
||||
"height": 412
|
||||
@@ -1384,7 +1384,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 6P": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 412,
|
||||
"height": 732
|
||||
@@ -1395,7 +1395,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 6P landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 732,
|
||||
"height": 412
|
||||
@@ -1406,7 +1406,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 7": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 600,
|
||||
"height": 960
|
||||
@@ -1417,7 +1417,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 7 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 960,
|
||||
"height": 600
|
||||
@@ -1472,7 +1472,7 @@
|
||||
"defaultBrowserType": "webkit"
|
||||
},
|
||||
"Pixel 2": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 411,
|
||||
"height": 731
|
||||
@@ -1483,7 +1483,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 2 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 731,
|
||||
"height": 411
|
||||
@@ -1494,7 +1494,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 2 XL": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 411,
|
||||
"height": 823
|
||||
@@ -1505,7 +1505,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 2 XL landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 823,
|
||||
"height": 411
|
||||
@@ -1516,7 +1516,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 3": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 393,
|
||||
"height": 786
|
||||
@@ -1527,7 +1527,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 3 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 786,
|
||||
"height": 393
|
||||
@@ -1538,7 +1538,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 4": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 353,
|
||||
"height": 745
|
||||
@@ -1549,7 +1549,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 4 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 745,
|
||||
"height": 353
|
||||
@@ -1560,7 +1560,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 4a (5G)": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"screen": {
|
||||
"width": 412,
|
||||
"height": 892
|
||||
@@ -1575,7 +1575,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 4a (5G) landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"screen": {
|
||||
"height": 892,
|
||||
"width": 412
|
||||
@@ -1590,7 +1590,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 5": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"screen": {
|
||||
"width": 393,
|
||||
"height": 851
|
||||
@@ -1605,7 +1605,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 5 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"screen": {
|
||||
"width": 851,
|
||||
"height": 393
|
||||
@@ -1620,7 +1620,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 7": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"screen": {
|
||||
"width": 412,
|
||||
"height": 915
|
||||
@@ -1635,7 +1635,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 7 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"screen": {
|
||||
"width": 915,
|
||||
"height": 412
|
||||
@@ -1650,7 +1650,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Moto G4": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 360,
|
||||
"height": 640
|
||||
@@ -1661,7 +1661,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Moto G4 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 640,
|
||||
"height": 360
|
||||
@@ -1672,7 +1672,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Desktop Chrome HiDPI": {
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Safari/537.36",
|
||||
"screen": {
|
||||
"width": 1792,
|
||||
"height": 1120
|
||||
@@ -1687,7 +1687,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Desktop Edge HiDPI": {
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Safari/537.36 Edg/143.0.7499.4",
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Safari/537.36 Edg/145.0.7632.6",
|
||||
"screen": {
|
||||
"width": 1792,
|
||||
"height": 1120
|
||||
@@ -1702,7 +1702,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Desktop Firefox HiDPI": {
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:144.0.2) Gecko/20100101 Firefox/144.0.2",
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:146.0.1) Gecko/20100101 Firefox/146.0.1",
|
||||
"screen": {
|
||||
"width": 1792,
|
||||
"height": 1120
|
||||
@@ -1732,7 +1732,7 @@
|
||||
"defaultBrowserType": "webkit"
|
||||
},
|
||||
"Desktop Chrome": {
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Safari/537.36",
|
||||
"screen": {
|
||||
"width": 1920,
|
||||
"height": 1080
|
||||
@@ -1747,7 +1747,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Desktop Edge": {
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.7499.4 Safari/537.36 Edg/143.0.7499.4",
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.7632.6 Safari/537.36 Edg/145.0.7632.6",
|
||||
"screen": {
|
||||
"width": 1920,
|
||||
"height": 1080
|
||||
@@ -1762,7 +1762,7 @@
|
||||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Desktop Firefox": {
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:144.0.2) Gecko/20100101 Firefox/144.0.2",
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:146.0.1) Gecko/20100101 Firefox/146.0.1",
|
||||
"screen": {
|
||||
"width": 1920,
|
||||
"height": 1080
|
||||
|
||||
3
node_modules/playwright-core/lib/server/dispatchers/browserContextDispatcher.js
generated
vendored
3
node_modules/playwright-core/lib/server/dispatchers/browserContextDispatcher.js
generated
vendored
@@ -298,6 +298,9 @@ class BrowserContextDispatcher extends import_dispatcher.Dispatcher {
|
||||
if (recorder)
|
||||
recorder.setMode("none");
|
||||
}
|
||||
async exposeConsoleApi(params, progress) {
|
||||
await this._context.exposeConsoleApi();
|
||||
}
|
||||
async pause(params, progress) {
|
||||
}
|
||||
async newCDPSession(params, progress) {
|
||||
|
||||
19
node_modules/playwright-core/lib/server/dispatchers/dispatcher.js
generated
vendored
19
node_modules/playwright-core/lib/server/dispatchers/dispatcher.js
generated
vendored
@@ -85,11 +85,7 @@ class Dispatcher extends import_events.EventEmitter {
|
||||
this.connection.sendAdopt(this, child);
|
||||
}
|
||||
async _runCommand(callMetadata, method, validParams) {
|
||||
const controller = new import_progress.ProgressController(callMetadata, (message) => {
|
||||
const logName = this._object.logName || "api";
|
||||
import_utils.debugLogger.log(logName, message);
|
||||
this._object.instrumentation.onCallLog(this._object, callMetadata, logName, message);
|
||||
});
|
||||
const controller = import_progress.ProgressController.createForSdkObject(this._object, callMetadata);
|
||||
this._activeProgressControllers.add(controller);
|
||||
try {
|
||||
return await controller.run((progress) => this[method](validParams, progress), validParams?.timeout);
|
||||
@@ -106,7 +102,7 @@ class Dispatcher extends import_events.EventEmitter {
|
||||
this.connection.sendEvent(this, method, params);
|
||||
}
|
||||
_dispose(reason) {
|
||||
this._disposeRecursively(new import_errors.TargetClosedError());
|
||||
this._disposeRecursively(new import_errors.TargetClosedError(this._object.closeReason()));
|
||||
this.connection.sendDispose(this, reason);
|
||||
}
|
||||
_onDispose() {
|
||||
@@ -257,7 +253,7 @@ class DispatcherConnection {
|
||||
const { id, guid, method, params, metadata } = message;
|
||||
const dispatcher = this._dispatcherByGuid.get(guid);
|
||||
if (!dispatcher) {
|
||||
this.onmessage({ id, error: (0, import_errors.serializeError)(new import_errors.TargetClosedError()) });
|
||||
this.onmessage({ id, error: (0, import_errors.serializeError)(new import_errors.TargetClosedError(void 0)) });
|
||||
return;
|
||||
}
|
||||
let validParams;
|
||||
@@ -325,19 +321,19 @@ class DispatcherConnection {
|
||||
const response = { id };
|
||||
try {
|
||||
if (this._dispatcherByGuid.get(guid) !== dispatcher)
|
||||
throw new import_errors.TargetClosedError(closeReason(sdkObject));
|
||||
throw new import_errors.TargetClosedError(sdkObject.closeReason());
|
||||
const result = await dispatcher._runCommand(callMetadata, method, validParams);
|
||||
const validator = (0, import_validator.findValidator)(dispatcher._type, method, "Result");
|
||||
response.result = validator(result, "", this._validatorToWireContext());
|
||||
callMetadata.result = result;
|
||||
} catch (e) {
|
||||
if ((0, import_errors.isTargetClosedError)(e)) {
|
||||
const reason = closeReason(sdkObject);
|
||||
const reason = sdkObject.closeReason();
|
||||
if (reason)
|
||||
(0, import_utils.rewriteErrorMessage)(e, reason);
|
||||
} else if ((0, import_protocolError.isProtocolError)(e)) {
|
||||
if (e.type === "closed")
|
||||
e = new import_errors.TargetClosedError(closeReason(sdkObject), e.browserLogMessage());
|
||||
e = new import_errors.TargetClosedError(sdkObject.closeReason(), e.browserLogMessage());
|
||||
else if (e.type === "crashed")
|
||||
(0, import_utils.rewriteErrorMessage)(e, "Target crashed " + e.browserLogMessage());
|
||||
}
|
||||
@@ -359,9 +355,6 @@ class DispatcherConnection {
|
||||
await new Promise((f) => setTimeout(f, slowMo));
|
||||
}
|
||||
}
|
||||
function closeReason(sdkObject) {
|
||||
return sdkObject.attribution.page?.closeReason || sdkObject.attribution.context?._closeReason || sdkObject.attribution.browser?._closeReason;
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
Dispatcher,
|
||||
|
||||
2
node_modules/playwright-core/lib/server/dispatchers/frameDispatcher.js
generated
vendored
2
node_modules/playwright-core/lib/server/dispatchers/frameDispatcher.js
generated
vendored
@@ -212,7 +212,7 @@ class FrameDispatcher extends import_dispatcher.Dispatcher {
|
||||
let expectedValue = params.expectedValue ? (0, import_jsHandleDispatcher.parseArgument)(params.expectedValue) : void 0;
|
||||
if (params.expression === "to.match.aria" && expectedValue)
|
||||
expectedValue = (0, import_ariaSnapshot.parseAriaSnapshotUnsafe)(import_utilsBundle.yaml, expectedValue);
|
||||
const result = await this._frame.expect(progress, params.selector, { ...params, expectedValue }, params.timeout);
|
||||
const result = await this._frame.expect(progress, params.selector, { ...params, expectedValue, timeoutForLogs: params.timeout });
|
||||
if (result.received !== void 0)
|
||||
result.received = (0, import_jsHandleDispatcher.serializeResult)(result.received);
|
||||
return result;
|
||||
|
||||
96
node_modules/playwright-core/lib/server/dispatchers/pageAgentDispatcher.js
generated
vendored
Normal file
96
node_modules/playwright-core/lib/server/dispatchers/pageAgentDispatcher.js
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var pageAgentDispatcher_exports = {};
|
||||
__export(pageAgentDispatcher_exports, {
|
||||
PageAgentDispatcher: () => PageAgentDispatcher
|
||||
});
|
||||
module.exports = __toCommonJS(pageAgentDispatcher_exports);
|
||||
var import_dispatcher = require("./dispatcher");
|
||||
var import_pageAgent = require("../agent/pageAgent");
|
||||
var import_instrumentation = require("../instrumentation");
|
||||
var import_context = require("../agent/context");
|
||||
class PageAgentDispatcher extends import_dispatcher.Dispatcher {
|
||||
constructor(scope, options) {
|
||||
super(scope, new import_instrumentation.SdkObject(scope._object, "pageAgent"), "PageAgent", { page: scope });
|
||||
this._type_PageAgent = true;
|
||||
this._type_EventTarget = true;
|
||||
this._usage = { turns: 0, inputTokens: 0, outputTokens: 0 };
|
||||
this._page = scope._object;
|
||||
this._context = new import_context.Context(this._page, options, this._eventSupport());
|
||||
}
|
||||
async perform(params, progress) {
|
||||
try {
|
||||
await (0, import_pageAgent.pageAgentPerform)(progress, this._context, params.task, params);
|
||||
} finally {
|
||||
this._context.pushHistory({ type: "perform", description: params.task });
|
||||
}
|
||||
return { usage: this._usage };
|
||||
}
|
||||
async expect(params, progress) {
|
||||
try {
|
||||
await (0, import_pageAgent.pageAgentExpect)(progress, this._context, params.expectation, params);
|
||||
} finally {
|
||||
this._context.pushHistory({ type: "expect", description: params.expectation });
|
||||
}
|
||||
return { usage: this._usage };
|
||||
}
|
||||
async extract(params, progress) {
|
||||
const result = await (0, import_pageAgent.pageAgentExtract)(progress, this._context, params.query, params.schema, params);
|
||||
return { result, usage: this._usage };
|
||||
}
|
||||
async usage(params, progress) {
|
||||
return { usage: this._usage };
|
||||
}
|
||||
async dispose(params, progress) {
|
||||
progress.metadata.potentiallyClosesScope = true;
|
||||
void this.stopPendingOperations(new Error("The agent is disposed"));
|
||||
this._dispose();
|
||||
}
|
||||
_eventSupport() {
|
||||
const self = this;
|
||||
return {
|
||||
onBeforeTurn(params) {
|
||||
const userMessage = params.conversation.messages.find((m) => m.role === "user");
|
||||
self._dispatchEvent("turn", { role: "user", message: userMessage?.content ?? "" });
|
||||
},
|
||||
onAfterTurn(params) {
|
||||
const usage = { inputTokens: params.totalUsage.input, outputTokens: params.totalUsage.output };
|
||||
const intent = params.assistantMessage.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
|
||||
self._dispatchEvent("turn", { role: "assistant", message: intent, usage });
|
||||
if (!params.assistantMessage.content.filter((c) => c.type === "tool_call").length)
|
||||
self._dispatchEvent("turn", { role: "assistant", message: `no tool calls`, usage });
|
||||
self._usage = { turns: self._usage.turns + 1, inputTokens: self._usage.inputTokens + usage.inputTokens, outputTokens: self._usage.outputTokens + usage.outputTokens };
|
||||
},
|
||||
onBeforeToolCall(params) {
|
||||
self._dispatchEvent("turn", { role: "assistant", message: `call tool "${params.toolCall.name}"` });
|
||||
},
|
||||
onAfterToolCall(params) {
|
||||
const suffix = params.toolCall.result?.isError ? "failed" : "succeeded";
|
||||
self._dispatchEvent("turn", { role: "user", message: `tool "${params.toolCall.name}" ${suffix}` });
|
||||
},
|
||||
onToolCallError(params) {
|
||||
self._dispatchEvent("turn", { role: "user", message: `tool "${params.toolCall.name}" failed: ${params.error.message}` });
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
PageAgentDispatcher
|
||||
});
|
||||
4
node_modules/playwright-core/lib/server/dispatchers/pageDispatcher.js
generated
vendored
4
node_modules/playwright-core/lib/server/dispatchers/pageDispatcher.js
generated
vendored
@@ -36,6 +36,7 @@ var import_networkDispatchers3 = require("./networkDispatchers");
|
||||
var import_webSocketRouteDispatcher = require("./webSocketRouteDispatcher");
|
||||
var import_instrumentation = require("../instrumentation");
|
||||
var import_urlMatch = require("../../utils/isomorphic/urlMatch");
|
||||
var import_pageAgentDispatcher = require("./pageAgentDispatcher");
|
||||
class PageDispatcher extends import_dispatcher.Dispatcher {
|
||||
constructor(parentScope, page) {
|
||||
const mainFrame = import_frameDispatcher.FrameDispatcher.from(parentScope, page.mainFrame());
|
||||
@@ -288,6 +289,9 @@ class PageDispatcher extends import_dispatcher.Dispatcher {
|
||||
const coverage = this._page.coverage;
|
||||
return await coverage.stopCSSCoverage();
|
||||
}
|
||||
async agent(params, progress) {
|
||||
return { agent: new import_pageAgentDispatcher.PageAgentDispatcher(this, params) };
|
||||
}
|
||||
_onFrameAttached(frame) {
|
||||
this._dispatchEvent("frameAttached", { frame: import_frameDispatcher.FrameDispatcher.from(this.parentScope(), frame) });
|
||||
}
|
||||
|
||||
15
node_modules/playwright-core/lib/server/dom.js
generated
vendored
15
node_modules/playwright-core/lib/server/dom.js
generated
vendored
@@ -255,6 +255,7 @@ class ElementHandle extends js.JSHandle {
|
||||
async _retryAction(progress, actionName, action, options) {
|
||||
let retry = 0;
|
||||
const waitTime = [0, 20, 100, 100, 500];
|
||||
const noAutoWaiting = options.__testHookNoAutoWaiting ?? options.noAutoWaiting;
|
||||
while (true) {
|
||||
if (retry) {
|
||||
progress.log(`retrying ${actionName} action${options.trial ? " (trial run)" : ""}`);
|
||||
@@ -268,35 +269,43 @@ class ElementHandle extends js.JSHandle {
|
||||
} else {
|
||||
progress.log(`attempting ${actionName} action${options.trial ? " (trial run)" : ""}`);
|
||||
}
|
||||
if (!options.skipActionPreChecks && !options.force)
|
||||
if (!options.skipActionPreChecks && !options.force && !noAutoWaiting)
|
||||
await this._frame._page.performActionPreChecks(progress);
|
||||
const result = await action(retry);
|
||||
++retry;
|
||||
if (result === "error:notvisible") {
|
||||
if (options.force)
|
||||
if (options.force || noAutoWaiting)
|
||||
throw new NonRecoverableDOMError("Element is not visible");
|
||||
progress.log(" element is not visible");
|
||||
continue;
|
||||
}
|
||||
if (result === "error:notinviewport") {
|
||||
if (options.force)
|
||||
if (options.force || noAutoWaiting)
|
||||
throw new NonRecoverableDOMError("Element is outside of the viewport");
|
||||
progress.log(" element is outside of the viewport");
|
||||
continue;
|
||||
}
|
||||
if (result === "error:optionsnotfound") {
|
||||
if (noAutoWaiting)
|
||||
throw new NonRecoverableDOMError("Did not find some options");
|
||||
progress.log(" did not find some options");
|
||||
continue;
|
||||
}
|
||||
if (result === "error:optionnotenabled") {
|
||||
if (noAutoWaiting)
|
||||
throw new NonRecoverableDOMError("Option being selected is not enabled");
|
||||
progress.log(" option being selected is not enabled");
|
||||
continue;
|
||||
}
|
||||
if (typeof result === "object" && "hitTargetDescription" in result) {
|
||||
if (noAutoWaiting)
|
||||
throw new NonRecoverableDOMError(`${result.hitTargetDescription} intercepts pointer events`);
|
||||
progress.log(` ${result.hitTargetDescription} intercepts pointer events`);
|
||||
continue;
|
||||
}
|
||||
if (typeof result === "object" && "missingState" in result) {
|
||||
if (noAutoWaiting)
|
||||
throw new NonRecoverableDOMError(`Element is not ${result.missingState}`);
|
||||
progress.log(` element is not ${result.missingState}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
7
node_modules/playwright-core/lib/server/electron/electron.js
generated
vendored
7
node_modules/playwright-core/lib/server/electron/electron.js
generated
vendored
@@ -158,8 +158,8 @@ class Electron extends import_instrumentation.SdkObject {
|
||||
let shell = false;
|
||||
if (process.platform === "win32") {
|
||||
shell = true;
|
||||
command = `"${command}"`;
|
||||
electronArguments = electronArguments.map((arg) => `"${arg}"`);
|
||||
command = [command, ...electronArguments].map((arg) => `"${escapeDoubleQuotes(arg)}"`).join(" ");
|
||||
electronArguments = [];
|
||||
}
|
||||
delete env.NODE_OPTIONS;
|
||||
const { launchedProcess, gracefullyClose, kill } = await (0, import_processLauncher.launchProcess)({
|
||||
@@ -263,6 +263,9 @@ async function waitForLine(progress, process2, regex) {
|
||||
import_eventsHelper.eventsHelper.removeEventListeners(listeners);
|
||||
}
|
||||
}
|
||||
function escapeDoubleQuotes(str) {
|
||||
return str.replace(/"/g, '\\"');
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
Electron,
|
||||
|
||||
30
node_modules/playwright-core/lib/server/firefox/ffBrowser.js
generated
vendored
30
node_modules/playwright-core/lib/server/firefox/ffBrowser.js
generated
vendored
@@ -54,7 +54,6 @@ class FFBrowser extends import_browser.Browser {
|
||||
this.session.on("Browser.detachedFromTarget", this._onDetachedFromTarget.bind(this));
|
||||
this.session.on("Browser.downloadCreated", this._onDownloadCreated.bind(this));
|
||||
this.session.on("Browser.downloadFinished", this._onDownloadFinished.bind(this));
|
||||
this.session.on("Browser.videoRecordingFinished", this._onVideoRecordingFinished.bind(this));
|
||||
}
|
||||
static async connect(parent, transport, options) {
|
||||
const connection = new import_ffConnection.FFConnection(transport, options.protocolLogger, options.browserLogsCollector);
|
||||
@@ -141,12 +140,9 @@ class FFBrowser extends import_browser.Browser {
|
||||
const error = payload.canceled ? "canceled" : payload.error;
|
||||
this._downloadFinished(payload.uuid, error);
|
||||
}
|
||||
_onVideoRecordingFinished(payload) {
|
||||
this._takeVideo(payload.screencastId)?.reportFinished();
|
||||
}
|
||||
_onDisconnect() {
|
||||
for (const video of this._idToVideo.values())
|
||||
video.artifact.reportFinished(new import_errors.TargetClosedError());
|
||||
video.artifact.reportFinished(new import_errors.TargetClosedError(this.closeReason()));
|
||||
this._idToVideo.clear();
|
||||
for (const ffPage of this._ffPages.values())
|
||||
ffPage.didClose();
|
||||
@@ -199,15 +195,13 @@ class FFBrowserContext extends import_browserContext.BrowserContext {
|
||||
promises.push(this.doUpdateOffline());
|
||||
promises.push(this.doUpdateDefaultEmulatedMedia());
|
||||
if (this._options.recordVideo) {
|
||||
promises.push(this._ensureVideosPath().then(() => {
|
||||
return this._browser.session.send("Browser.setVideoRecordingOptions", {
|
||||
// validateBrowserContextOptions ensures correct video size.
|
||||
options: {
|
||||
...this._options.recordVideo.size,
|
||||
dir: this._options.recordVideo.dir
|
||||
},
|
||||
browserContextId: this._browserContextId
|
||||
});
|
||||
promises.push(this._browser.session.send("Browser.setScreencastOptions", {
|
||||
// validateBrowserContextOptions ensures correct video size.
|
||||
options: {
|
||||
...this._options.recordVideo.size,
|
||||
quality: 90
|
||||
},
|
||||
browserContextId: this._browserContextId
|
||||
}));
|
||||
}
|
||||
const proxy = this._options.proxyOverride || this._options.proxy;
|
||||
@@ -379,12 +373,8 @@ class FFBrowserContext extends import_browserContext.BrowserContext {
|
||||
}
|
||||
async doClose(reason) {
|
||||
if (!this._browserContextId) {
|
||||
if (this._options.recordVideo) {
|
||||
await this._browser.session.send("Browser.setVideoRecordingOptions", {
|
||||
options: void 0,
|
||||
browserContextId: this._browserContextId
|
||||
});
|
||||
}
|
||||
if (this._options.recordVideo)
|
||||
await Promise.all(this._ffPages().map((ffPage) => ffPage._page.screencast.stopVideoRecording()));
|
||||
await this._browser.close({ reason });
|
||||
} else {
|
||||
await this._browser.session.send("Browser.removeBrowserContext", { browserContextId: this._browserContextId });
|
||||
|
||||
5
node_modules/playwright-core/lib/server/firefox/ffConnection.js
generated
vendored
5
node_modules/playwright-core/lib/server/firefox/ffConnection.js
generated
vendored
@@ -90,11 +90,6 @@ class FFSession extends import_events.EventEmitter {
|
||||
this._connection = connection;
|
||||
this._sessionId = sessionId;
|
||||
this._rawSend = rawSend;
|
||||
this.on = super.on;
|
||||
this.addListener = super.addListener;
|
||||
this.off = super.removeListener;
|
||||
this.removeListener = super.removeListener;
|
||||
this.once = super.once;
|
||||
}
|
||||
markAsCrashed() {
|
||||
this._crashed = true;
|
||||
|
||||
4
node_modules/playwright-core/lib/server/firefox/ffNetworkManager.js
generated
vendored
4
node_modules/playwright-core/lib/server/firefox/ffNetworkManager.js
generated
vendored
@@ -170,9 +170,9 @@ const causeToResourceType = {
|
||||
TYPE_FONT: "font",
|
||||
TYPE_MEDIA: "media",
|
||||
TYPE_WEBSOCKET: "websocket",
|
||||
TYPE_CSP_REPORT: "other",
|
||||
TYPE_CSP_REPORT: "cspreport",
|
||||
TYPE_XSLT: "other",
|
||||
TYPE_BEACON: "other",
|
||||
TYPE_BEACON: "beacon",
|
||||
TYPE_FETCH: "fetch",
|
||||
TYPE_IMAGESET: "image",
|
||||
TYPE_WEB_MANIFEST: "manifest"
|
||||
|
||||
33
node_modules/playwright-core/lib/server/firefox/ffPage.js
generated
vendored
33
node_modules/playwright-core/lib/server/firefox/ffPage.js
generated
vendored
@@ -41,9 +41,9 @@ var import_ffConnection = require("./ffConnection");
|
||||
var import_ffExecutionContext = require("./ffExecutionContext");
|
||||
var import_ffInput = require("./ffInput");
|
||||
var import_ffNetworkManager = require("./ffNetworkManager");
|
||||
var import_debugLogger = require("../utils/debugLogger");
|
||||
var import_stackTrace = require("../../utils/isomorphic/stackTrace");
|
||||
var import_errors = require("../errors");
|
||||
var import_debugLogger = require("../utils/debugLogger");
|
||||
const UTILITY_WORLD_NAME = "__playwright_utility_world__";
|
||||
class FFPage {
|
||||
constructor(session, browserContext, opener) {
|
||||
@@ -83,13 +83,16 @@ class FFPage {
|
||||
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.workerDestroyed", this._onWorkerDestroyed.bind(this)),
|
||||
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.dispatchMessageFromWorker", this._onDispatchMessageFromWorker.bind(this)),
|
||||
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.crashed", this._onCrashed.bind(this)),
|
||||
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.videoRecordingStarted", this._onVideoRecordingStarted.bind(this)),
|
||||
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketCreated", this._onWebSocketCreated.bind(this)),
|
||||
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketClosed", this._onWebSocketClosed.bind(this)),
|
||||
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketFrameReceived", this._onWebSocketFrameReceived.bind(this)),
|
||||
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketFrameSent", this._onWebSocketFrameSent.bind(this)),
|
||||
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.screencastFrame", this._onScreencastFrame.bind(this))
|
||||
];
|
||||
const screencast = this._page.screencast;
|
||||
const videoOptions = screencast.launchVideoRecorder();
|
||||
if (videoOptions)
|
||||
screencast.startVideoRecording(videoOptions).catch((e) => import_debugLogger.debugLogger.log("error", e));
|
||||
this._session.once("Page.ready", () => {
|
||||
if (this._reportedAsNew)
|
||||
return;
|
||||
@@ -272,11 +275,8 @@ class FFPage {
|
||||
this._session.markAsCrashed();
|
||||
this._page._didCrash();
|
||||
}
|
||||
_onVideoRecordingStarted(event) {
|
||||
this._browserContext._browser._videoStarted(this._browserContext, event.screencastId, event.file, this._page.waitForInitializedOrError());
|
||||
}
|
||||
didClose() {
|
||||
this._markAsError(new import_errors.TargetClosedError());
|
||||
this._markAsError(new import_errors.TargetClosedError(this._page.closeReason()));
|
||||
this._session.dispose();
|
||||
import_eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
|
||||
this._networkManager.dispose();
|
||||
@@ -417,24 +417,21 @@ class FFPage {
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
async setScreencastOptions(options) {
|
||||
if (options) {
|
||||
const { screencastId } = await this._session.send("Page.startScreencast", options);
|
||||
this._screencastId = screencastId;
|
||||
} else {
|
||||
await this._session.send("Page.stopScreencast");
|
||||
}
|
||||
async startScreencast(options) {
|
||||
await this._session.send("Page.startScreencast", options);
|
||||
}
|
||||
async stopScreencast() {
|
||||
await this._session.sendMayFail("Page.stopScreencast");
|
||||
}
|
||||
_onScreencastFrame(event) {
|
||||
if (!this._screencastId)
|
||||
return;
|
||||
const screencastId = this._screencastId;
|
||||
this._page.throttleScreencastFrameAck(() => {
|
||||
this._session.send("Page.screencastFrameAck", { screencastId }).catch((e) => import_debugLogger.debugLogger.log("error", e));
|
||||
this._page.screencast.throttleFrameAck(() => {
|
||||
this._session.sendMayFail("Page.screencastFrameAck");
|
||||
});
|
||||
const buffer = Buffer.from(event.data, "base64");
|
||||
this._page.emit(import_page2.Page.Events.ScreencastFrame, {
|
||||
buffer,
|
||||
frameSwapWallTime: event.timestamp * 1e3,
|
||||
// timestamp is in seconds, we need to convert to milliseconds.
|
||||
width: event.deviceWidth,
|
||||
height: event.deviceHeight
|
||||
});
|
||||
|
||||
14
node_modules/playwright-core/lib/server/firefox/firefox.js
generated
vendored
14
node_modules/playwright-core/lib/server/firefox/firefox.js
generated
vendored
@@ -56,15 +56,13 @@ class Firefox extends import_browserType.BrowserType {
|
||||
connectToTransport(transport, options) {
|
||||
return import_ffBrowser.FFBrowser.connect(this.attribution.playwright, transport, options);
|
||||
}
|
||||
doRewriteStartupLog(error) {
|
||||
if (!error.logs)
|
||||
return error;
|
||||
if (error.logs.includes(`as root in a regular user's session is not supported.`))
|
||||
error.logs = "\n" + (0, import_ascii.wrapInASCIIBox)(`Firefox is unable to launch if the $HOME folder isn't owned by the current user.
|
||||
doRewriteStartupLog(logs) {
|
||||
if (logs.includes(`as root in a regular user's session is not supported.`))
|
||||
logs = "\n" + (0, import_ascii.wrapInASCIIBox)(`Firefox is unable to launch if the $HOME folder isn't owned by the current user.
|
||||
Workaround: Set the HOME=/root environment variable${process.env.GITHUB_ACTION ? " in your GitHub Actions workflow file" : ""} when running Playwright.`, 1);
|
||||
if (error.logs.includes("no DISPLAY environment variable specified"))
|
||||
error.logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
|
||||
return error;
|
||||
if (logs.includes("no DISPLAY environment variable specified"))
|
||||
logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
|
||||
return logs;
|
||||
}
|
||||
amendEnvironment(env) {
|
||||
if (!import_path.default.isAbsolute(import_os.default.homedir()))
|
||||
|
||||
12
node_modules/playwright-core/lib/server/frameSelectors.js
generated
vendored
12
node_modules/playwright-core/lib/server/frameSelectors.js
generated
vendored
@@ -50,7 +50,9 @@ class FrameSelectors {
|
||||
if (!resolved)
|
||||
throw new Error(`Failed to find frame for selector "${selector}"`);
|
||||
return await resolved.injected.evaluateHandle((injected, { info, scope: scope2 }) => {
|
||||
return injected.querySelectorAll(info.parsed, scope2 || document);
|
||||
const elements = injected.querySelectorAll(info.parsed, scope2 || document);
|
||||
injected.checkDeprecatedSelectorUsage(info.parsed, elements);
|
||||
return elements;
|
||||
}, { info: resolved.info, scope: resolved.scope });
|
||||
}
|
||||
async queryCount(selector, options) {
|
||||
@@ -59,7 +61,9 @@ class FrameSelectors {
|
||||
throw new Error(`Failed to find frame for selector "${selector}"`);
|
||||
await options.__testHookBeforeQuery?.();
|
||||
return await resolved.injected.evaluate((injected, { info }) => {
|
||||
return injected.querySelectorAll(info.parsed, document).length;
|
||||
const elements = injected.querySelectorAll(info.parsed, document);
|
||||
injected.checkDeprecatedSelectorUsage(info.parsed, elements);
|
||||
return elements.length;
|
||||
}, { info: resolved.info });
|
||||
}
|
||||
async queryAll(selector, scope) {
|
||||
@@ -67,7 +71,9 @@ class FrameSelectors {
|
||||
if (!resolved)
|
||||
return [];
|
||||
const arrayHandle = await resolved.injected.evaluateHandle((injected, { info, scope: scope2 }) => {
|
||||
return injected.querySelectorAll(info.parsed, scope2 || document);
|
||||
const elements = injected.querySelectorAll(info.parsed, scope2 || document);
|
||||
injected.checkDeprecatedSelectorUsage(info.parsed, elements);
|
||||
return elements;
|
||||
}, { info: resolved.info, scope: resolved.scope });
|
||||
const properties = await arrayHandle.getProperties();
|
||||
arrayHandle.dispose();
|
||||
|
||||
82
node_modules/playwright-core/lib/server/frames.js
generated
vendored
82
node_modules/playwright-core/lib/server/frames.js
generated
vendored
@@ -350,6 +350,11 @@ class FrameManager {
|
||||
frame.emit(Frame.Events.InternalNavigation, event);
|
||||
}
|
||||
}
|
||||
const FrameEvent = {
|
||||
InternalNavigation: "internalnavigation",
|
||||
AddLifecycle: "addlifecycle",
|
||||
RemoveLifecycle: "removelifecycle"
|
||||
};
|
||||
class Frame extends import_instrumentation.SdkObject {
|
||||
constructor(page, id, parentFrame) {
|
||||
super(page, "frame");
|
||||
@@ -382,11 +387,7 @@ class Frame extends import_instrumentation.SdkObject {
|
||||
this._startNetworkIdleTimer();
|
||||
}
|
||||
static {
|
||||
this.Events = {
|
||||
InternalNavigation: "internalnavigation",
|
||||
AddLifecycle: "addlifecycle",
|
||||
RemoveLifecycle: "removelifecycle"
|
||||
};
|
||||
this.Events = FrameEvent;
|
||||
}
|
||||
isDetached() {
|
||||
return this._detachedScope.isClosed();
|
||||
@@ -569,7 +570,7 @@ class Frame extends import_instrumentation.SdkObject {
|
||||
const request = navigationEvent.newDocument ? navigationEvent.newDocument.request : void 0;
|
||||
return request ? progress.race(request._finalRequest().response()) : null;
|
||||
}
|
||||
async _waitForLoadState(progress, state) {
|
||||
async waitForLoadState(progress, state) {
|
||||
const waitUntil = verifyLifecycle("state", state);
|
||||
if (!this._firedLifecycleEvents.has(waitUntil))
|
||||
await import_helper.helper.waitForEvent(progress, this, Frame.Events.AddLifecycle, (e) => e === waitUntil).promise;
|
||||
@@ -640,6 +641,7 @@ class Frame extends import_instrumentation.SdkObject {
|
||||
} else if (element2) {
|
||||
log2 = ` locator resolved to ${visible2 ? "visible" : "hidden"} ${injected.previewNode(element2)}`;
|
||||
}
|
||||
injected.checkDeprecatedSelectorUsage(info.parsed, elements);
|
||||
return { log: log2, element: element2, visible: visible2, attached: !!element2 };
|
||||
}, { info: resolved.info, root: resolved.frame === this ? scope : void 0 }));
|
||||
const { log, visible, attached } = await progress.race(result.evaluate((r) => ({ log: r.log, visible: r.visible, attached: r.attached })));
|
||||
@@ -735,7 +737,7 @@ class Frame extends import_instrumentation.SdkObject {
|
||||
this._onClearLifecycle();
|
||||
tagPromise.resolve();
|
||||
});
|
||||
const lifecyclePromise = progress.race(tagPromise).then(() => this._waitForLoadState(progress, waitUntil));
|
||||
const lifecyclePromise = progress.race(tagPromise).then(() => this.waitForLoadState(progress, waitUntil));
|
||||
const contentPromise = progress.race(context.evaluate(({ html: html2, tag: tag2 }) => {
|
||||
document.open();
|
||||
console.debug(tag2);
|
||||
@@ -905,14 +907,19 @@ class Frame extends import_instrumentation.SdkObject {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
async _retryWithProgressIfNotConnected(progress, selector, strict, performActionPreChecks, action) {
|
||||
async _retryWithProgressIfNotConnected(progress, selector, options, action) {
|
||||
progress.log(`waiting for ${this._asLocator(selector)}`);
|
||||
const noAutoWaiting = options.__testHookNoAutoWaiting ?? options.noAutoWaiting;
|
||||
const performActionPreChecks = (options.performActionPreChecks ?? !options.force) && !noAutoWaiting;
|
||||
return this.retryWithProgressAndTimeouts(progress, [0, 20, 50, 100, 100, 500], async (continuePolling) => {
|
||||
if (performActionPreChecks)
|
||||
await this._page.performActionPreChecks(progress);
|
||||
const resolved = await progress.race(this.selectors.resolveInjectedForSelector(selector, { strict }));
|
||||
if (!resolved)
|
||||
const resolved = await progress.race(this.selectors.resolveInjectedForSelector(selector, { strict: options.strict }));
|
||||
if (!resolved) {
|
||||
if (noAutoWaiting)
|
||||
throw new dom.NonRecoverableDOMError("Element(s) not found");
|
||||
return continuePolling;
|
||||
}
|
||||
const result = await progress.race(resolved.injected.evaluateHandle((injected, { info, callId }) => {
|
||||
const elements = injected.querySelectorAll(info.parsed, document);
|
||||
if (callId)
|
||||
@@ -926,12 +933,15 @@ class Frame extends import_instrumentation.SdkObject {
|
||||
} else if (element2) {
|
||||
log2 = ` locator resolved to ${injected.previewNode(element2)}`;
|
||||
}
|
||||
injected.checkDeprecatedSelectorUsage(info.parsed, elements);
|
||||
return { log: log2, success: !!element2, element: element2 };
|
||||
}, { info: resolved.info, callId: progress.metadata.id }));
|
||||
const { log, success } = await progress.race(result.evaluate((r) => ({ log: r.log, success: r.success })));
|
||||
if (log)
|
||||
progress.log(log);
|
||||
if (!success) {
|
||||
if (noAutoWaiting)
|
||||
throw new dom.NonRecoverableDOMError("Element(s) not found");
|
||||
result.dispose();
|
||||
return continuePolling;
|
||||
}
|
||||
@@ -940,6 +950,8 @@ class Frame extends import_instrumentation.SdkObject {
|
||||
try {
|
||||
const result2 = await action(element);
|
||||
if (result2 === "error:notconnected") {
|
||||
if (noAutoWaiting)
|
||||
throw new dom.NonRecoverableDOMError("Element is not attached to the DOM");
|
||||
progress.log("element was detached from the DOM, retrying");
|
||||
return continuePolling;
|
||||
}
|
||||
@@ -950,19 +962,19 @@ class Frame extends import_instrumentation.SdkObject {
|
||||
});
|
||||
}
|
||||
async rafrafTimeoutScreenshotElementWithProgress(progress, selector, timeout, options) {
|
||||
return await this._retryWithProgressIfNotConnected(progress, selector, true, true, async (handle) => {
|
||||
return await this._retryWithProgressIfNotConnected(progress, selector, { strict: true, performActionPreChecks: true }, async (handle) => {
|
||||
await handle._frame.rafrafTimeout(progress, timeout);
|
||||
return await this._page.screenshotter.screenshotElement(progress, handle, options);
|
||||
});
|
||||
}
|
||||
async click(progress, selector, options) {
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._click(progress, { ...options, waitAfter: !options.noWaitAfter })));
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._click(progress, { ...options, waitAfter: !options.noWaitAfter })));
|
||||
}
|
||||
async dblclick(progress, selector, options) {
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._dblclick(progress, options)));
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._dblclick(progress, options)));
|
||||
}
|
||||
async dragAndDrop(progress, source, target, options) {
|
||||
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, source, options.strict, !options.force, async (handle) => {
|
||||
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, source, options, async (handle) => {
|
||||
return handle._retryPointerAction(progress, "move and down", false, async (point) => {
|
||||
await this._page.mouse.move(progress, point.x, point.y);
|
||||
await this._page.mouse.down(progress);
|
||||
@@ -972,7 +984,7 @@ class Frame extends import_instrumentation.SdkObject {
|
||||
position: options.sourcePosition
|
||||
});
|
||||
}));
|
||||
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, options.strict, false, async (handle) => {
|
||||
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, { ...options, performActionPreChecks: false }, async (handle) => {
|
||||
return handle._retryPointerAction(progress, "move and up", false, async (point) => {
|
||||
await this._page.mouse.move(progress, point.x, point.y, { steps: options.steps });
|
||||
await this._page.mouse.up(progress);
|
||||
@@ -986,16 +998,16 @@ class Frame extends import_instrumentation.SdkObject {
|
||||
async tap(progress, selector, options) {
|
||||
if (!this._page.browserContext._options.hasTouch)
|
||||
throw new Error("The page does not support tap. Use hasTouch context option to enable touch support.");
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._tap(progress, options)));
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._tap(progress, options)));
|
||||
}
|
||||
async fill(progress, selector, value, options) {
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._fill(progress, value, options)));
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._fill(progress, value, options)));
|
||||
}
|
||||
async focus(progress, selector, options) {
|
||||
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true, (handle) => handle._focus(progress)));
|
||||
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._focus(progress)));
|
||||
}
|
||||
async blur(progress, selector, options) {
|
||||
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true, (handle) => handle._blur(progress)));
|
||||
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._blur(progress)));
|
||||
}
|
||||
async resolveSelector(progress, selector, options = {}) {
|
||||
const element = await progress.race(this.selectors.query(selector, options));
|
||||
@@ -1109,35 +1121,35 @@ class Frame extends import_instrumentation.SdkObject {
|
||||
return this._elementState(progress, selector, "checked", options, scope);
|
||||
}
|
||||
async hover(progress, selector, options) {
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._hover(progress, options)));
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._hover(progress, options)));
|
||||
}
|
||||
async selectOption(progress, selector, elements, values, options) {
|
||||
return await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._selectOption(progress, elements, values, options));
|
||||
return await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._selectOption(progress, elements, values, options));
|
||||
}
|
||||
async setInputFiles(progress, selector, params) {
|
||||
const inputFileItems = await (0, import_fileUploadUtils.prepareFilesForUpload)(this, params);
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, params.strict, true, (handle) => handle._setInputFiles(progress, inputFileItems)));
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, params, (handle) => handle._setInputFiles(progress, inputFileItems)));
|
||||
}
|
||||
async type(progress, selector, text, options) {
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true, (handle) => handle._type(progress, text, options)));
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._type(progress, text, options)));
|
||||
}
|
||||
async press(progress, selector, key, options) {
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true, (handle) => handle._press(progress, key, options)));
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._press(progress, key, options)));
|
||||
}
|
||||
async check(progress, selector, options) {
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._setChecked(progress, true, options)));
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._setChecked(progress, true, options)));
|
||||
}
|
||||
async uncheck(progress, selector, options) {
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force, (handle) => handle._setChecked(progress, false, options)));
|
||||
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._setChecked(progress, false, options)));
|
||||
}
|
||||
async waitForTimeout(progress, timeout) {
|
||||
return progress.wait(timeout);
|
||||
}
|
||||
async ariaSnapshot(progress, selector) {
|
||||
return await this._retryWithProgressIfNotConnected(progress, selector, true, true, (handle) => progress.race(handle.ariaSnapshot()));
|
||||
return await this._retryWithProgressIfNotConnected(progress, selector, { strict: true, performActionPreChecks: true }, (handle) => progress.race(handle.ariaSnapshot()));
|
||||
}
|
||||
async expect(progress, selector, options, timeout) {
|
||||
progress.log(`${(0, import_utils.renderTitleForCall)(progress.metadata)}${timeout ? ` with timeout ${timeout}ms` : ""}`);
|
||||
async expect(progress, selector, options) {
|
||||
progress.log(`${(0, import_utils.renderTitleForCall)(progress.metadata)}${options.timeoutForLogs ? ` with timeout ${options.timeoutForLogs}ms` : ""}`);
|
||||
const lastIntermediateResult = { isSet: false };
|
||||
const fixupMetadataError = (result) => {
|
||||
if (result.matches === options.isNot)
|
||||
@@ -1146,17 +1158,19 @@ class Frame extends import_instrumentation.SdkObject {
|
||||
try {
|
||||
if (selector)
|
||||
progress.log(`waiting for ${this._asLocator(selector)}`);
|
||||
await this._page.performActionPreChecks(progress);
|
||||
if (!options.noAutoWaiting)
|
||||
await this._page.performActionPreChecks(progress);
|
||||
try {
|
||||
const resultOneShot = await this._expectInternal(progress, selector, options, lastIntermediateResult, true);
|
||||
if (resultOneShot.matches !== options.isNot)
|
||||
if (options.noAutoWaiting || resultOneShot.matches !== options.isNot)
|
||||
return resultOneShot;
|
||||
} catch (e) {
|
||||
if (this.isNonRetriableError(e))
|
||||
if (options.noAutoWaiting || this.isNonRetriableError(e))
|
||||
throw e;
|
||||
}
|
||||
const result = await this.retryWithProgressAndTimeouts(progress, [100, 250, 500, 1e3], async (continuePolling) => {
|
||||
await this._page.performActionPreChecks(progress);
|
||||
if (!options.noAutoWaiting)
|
||||
await this._page.performActionPreChecks(progress);
|
||||
const { matches, received } = await this._expectInternal(progress, selector, options, lastIntermediateResult, false);
|
||||
if (matches === options.isNot) {
|
||||
return continuePolling;
|
||||
@@ -1200,6 +1214,8 @@ class Frame extends import_instrumentation.SdkObject {
|
||||
throw injected2.strictModeViolationError(info2.parsed, elements);
|
||||
else if (elements.length)
|
||||
log2 = ` locator resolved to ${injected2.previewNode(elements[0])}`;
|
||||
if (info2)
|
||||
injected2.checkDeprecatedSelectorUsage(info2.parsed, elements);
|
||||
return { log: log2, ...await injected2.expect(elements[0], options2, elements) };
|
||||
}, { info, options, callId: progress.metadata.id }));
|
||||
if (log)
|
||||
|
||||
3
node_modules/playwright-core/lib/server/instrumentation.js
generated
vendored
3
node_modules/playwright-core/lib/server/instrumentation.js
generated
vendored
@@ -33,6 +33,9 @@ class SdkObject extends import_events.EventEmitter {
|
||||
this.attribution = { ...parent.attribution };
|
||||
this.instrumentation = parent.instrumentation;
|
||||
}
|
||||
closeReason() {
|
||||
return this.attribution.page?._closeReason || this.attribution.context?._closeReason || this.attribution.browser?._closeReason;
|
||||
}
|
||||
}
|
||||
function createRootSdkObject() {
|
||||
const fakeParent = { attribution: {}, instrumentation: createInstrumentation() };
|
||||
|
||||
62
node_modules/playwright-core/lib/server/network.js
generated
vendored
62
node_modules/playwright-core/lib/server/network.js
generated
vendored
@@ -22,6 +22,7 @@ __export(network_exports, {
|
||||
Response: () => Response,
|
||||
Route: () => Route,
|
||||
WebSocket: () => WebSocket,
|
||||
applyHeadersOverrides: () => applyHeadersOverrides,
|
||||
filterCookies: () => filterCookies,
|
||||
isLocalHostname: () => isLocalHostname,
|
||||
kMaxCookieExpiresDateInSeconds: () => kMaxCookieExpiresDateInSeconds,
|
||||
@@ -61,6 +62,48 @@ function filterCookies(cookies, urls) {
|
||||
function isLocalHostname(hostname) {
|
||||
return hostname === "localhost" || hostname.endsWith(".localhost");
|
||||
}
|
||||
const FORBIDDEN_HEADER_NAMES = /* @__PURE__ */ new Set([
|
||||
"accept-charset",
|
||||
"accept-encoding",
|
||||
"access-control-request-headers",
|
||||
"access-control-request-method",
|
||||
"connection",
|
||||
"content-length",
|
||||
"cookie",
|
||||
"date",
|
||||
"dnt",
|
||||
"expect",
|
||||
"host",
|
||||
"keep-alive",
|
||||
"origin",
|
||||
"referer",
|
||||
"set-cookie",
|
||||
"te",
|
||||
"trailer",
|
||||
"transfer-encoding",
|
||||
"upgrade",
|
||||
"via"
|
||||
]);
|
||||
const FORBIDDEN_METHODS = /* @__PURE__ */ new Set(["CONNECT", "TRACE", "TRACK"]);
|
||||
function isForbiddenHeader(name, value) {
|
||||
const lowerName = name.toLowerCase();
|
||||
if (FORBIDDEN_HEADER_NAMES.has(lowerName))
|
||||
return true;
|
||||
if (lowerName.startsWith("proxy-"))
|
||||
return true;
|
||||
if (lowerName.startsWith("sec-"))
|
||||
return true;
|
||||
if (lowerName === "x-http-method" || lowerName === "x-http-method-override" || lowerName === "x-method-override") {
|
||||
if (value && FORBIDDEN_METHODS.has(value.toUpperCase()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function applyHeadersOverrides(original, overrides) {
|
||||
const forbiddenHeaders = original.filter((header) => isForbiddenHeader(header.name, header.value));
|
||||
const allowedHeaders = overrides.filter((header) => !isForbiddenHeader(header.name, header.value));
|
||||
return mergeHeaders([allowedHeaders, forbiddenHeaders]);
|
||||
}
|
||||
const kMaxCookieExpiresDateInSeconds = 253402300799;
|
||||
function rewriteCookies(cookies) {
|
||||
return cookies.map((c) => {
|
||||
@@ -99,7 +142,6 @@ class Request extends import_instrumentation.SdkObject {
|
||||
this._response = null;
|
||||
this._redirectedTo = null;
|
||||
this._failureText = null;
|
||||
this._headersMap = /* @__PURE__ */ new Map();
|
||||
this._frame = null;
|
||||
this._serviceWorker = null;
|
||||
this._rawRequestHeadersPromise = new import_manualPromise.ManualPromise();
|
||||
@@ -118,7 +160,6 @@ class Request extends import_instrumentation.SdkObject {
|
||||
this._method = method;
|
||||
this._postData = postData;
|
||||
this._headers = headers;
|
||||
this._updateHeadersMap();
|
||||
this._isFavicon = url.endsWith("/favicon.ico") || !!redirectedFrom?._isFavicon;
|
||||
}
|
||||
static {
|
||||
@@ -132,13 +173,8 @@ class Request extends import_instrumentation.SdkObject {
|
||||
}
|
||||
_applyOverrides(overrides) {
|
||||
this._overrides = { ...this._overrides, ...overrides };
|
||||
this._updateHeadersMap();
|
||||
return this._overrides;
|
||||
}
|
||||
_updateHeadersMap() {
|
||||
for (const { name, value } of this.headers())
|
||||
this._headersMap.set(name.toLowerCase(), value);
|
||||
}
|
||||
overrides() {
|
||||
return this._overrides;
|
||||
}
|
||||
@@ -158,7 +194,8 @@ class Request extends import_instrumentation.SdkObject {
|
||||
return this._overrides?.headers || this._headers;
|
||||
}
|
||||
headerValue(name) {
|
||||
return this._headersMap.get(name);
|
||||
const lowerCaseName = name.toLowerCase();
|
||||
return this.headers().find((h) => h.name.toLowerCase() === lowerCaseName)?.value;
|
||||
}
|
||||
// "null" means no raw headers available - we'll use provisional headers as raw headers.
|
||||
setRawRequestHeaders(headers) {
|
||||
@@ -309,10 +346,7 @@ class Route extends import_instrumentation.SdkObject {
|
||||
throw new Error("New URL must have same protocol as overridden URL");
|
||||
}
|
||||
if (overrides.headers) {
|
||||
overrides.headers = overrides.headers?.filter((header) => {
|
||||
const headerName = header.name.toLowerCase();
|
||||
return headerName !== "cookie" && headerName !== "host";
|
||||
});
|
||||
overrides.headers = applyHeadersOverrides(this._request._headers, overrides.headers);
|
||||
}
|
||||
overrides = this._request._applyOverrides(overrides);
|
||||
const nextHandler = this._futureHandlers.shift();
|
||||
@@ -436,6 +470,9 @@ class Response extends import_instrumentation.SdkObject {
|
||||
request() {
|
||||
return this._request;
|
||||
}
|
||||
finished() {
|
||||
return this._finishedPromise;
|
||||
}
|
||||
frame() {
|
||||
return this._request.frame();
|
||||
}
|
||||
@@ -617,6 +654,7 @@ function mergeHeaders(headers) {
|
||||
Response,
|
||||
Route,
|
||||
WebSocket,
|
||||
applyHeadersOverrides,
|
||||
filterCookies,
|
||||
isLocalHostname,
|
||||
kMaxCookieExpiresDateInSeconds,
|
||||
|
||||
122
node_modules/playwright-core/lib/server/page.js
generated
vendored
122
node_modules/playwright-core/lib/server/page.js
generated
vendored
@@ -31,7 +31,8 @@ __export(page_exports, {
|
||||
InitScript: () => InitScript,
|
||||
Page: () => Page,
|
||||
PageBinding: () => PageBinding,
|
||||
Worker: () => Worker
|
||||
Worker: () => Worker,
|
||||
WorkerEvent: () => WorkerEvent
|
||||
});
|
||||
module.exports = __toCommonJS(page_exports);
|
||||
var import_browserContext = require("./browserContext");
|
||||
@@ -53,6 +54,22 @@ var import_manualPromise = require("../utils/isomorphic/manualPromise");
|
||||
var import_utilityScriptSerializers = require("../utils/isomorphic/utilityScriptSerializers");
|
||||
var import_callLog = require("./callLog");
|
||||
var rawBindingsControllerSource = __toESM(require("../generated/bindingsControllerSource"));
|
||||
var import_screencast = require("./screencast");
|
||||
const PageEvent = {
|
||||
Close: "close",
|
||||
Crash: "crash",
|
||||
Download: "download",
|
||||
EmulatedSizeChanged: "emulatedsizechanged",
|
||||
FileChooser: "filechooser",
|
||||
FrameAttached: "frameattached",
|
||||
FrameDetached: "framedetached",
|
||||
InternalFrameNavigatedToNewDocument: "internalframenavigatedtonewdocument",
|
||||
LocatorHandlerTriggered: "locatorhandlertriggered",
|
||||
ScreencastFrame: "screencastframe",
|
||||
Video: "video",
|
||||
WebSocket: "websocket",
|
||||
Worker: "worker"
|
||||
};
|
||||
class Page extends import_instrumentation.SdkObject {
|
||||
constructor(delegate, browserContext) {
|
||||
super(browserContext, "page");
|
||||
@@ -74,9 +91,6 @@ class Page extends import_instrumentation.SdkObject {
|
||||
this._lastLocatorHandlerUid = 0;
|
||||
this._locatorHandlerRunningCounter = 0;
|
||||
this._networkRequests = [];
|
||||
// Aiming at 25 fps by default - each frame is 40ms, but we give some slack with 35ms.
|
||||
// When throttling for tracing, 200ms between frames, except for 10 frames around the action.
|
||||
this._frameThrottler = new FrameThrottler(10, 35, 200);
|
||||
this.attribution.page = this;
|
||||
this.delegate = delegate;
|
||||
this.browserContext = browserContext;
|
||||
@@ -85,27 +99,14 @@ class Page extends import_instrumentation.SdkObject {
|
||||
this.touchscreen = new input.Touchscreen(delegate.rawTouchscreen, this);
|
||||
this.screenshotter = new import_screenshotter.Screenshotter(this);
|
||||
this.frameManager = new frames.FrameManager(this);
|
||||
this.screencast = new import_screencast.Screencast(this);
|
||||
if (delegate.pdf)
|
||||
this.pdf = delegate.pdf.bind(delegate);
|
||||
this.coverage = delegate.coverage ? delegate.coverage() : null;
|
||||
this.isStorageStatePage = browserContext.isCreatingStorageStatePage();
|
||||
}
|
||||
static {
|
||||
this.Events = {
|
||||
Close: "close",
|
||||
Crash: "crash",
|
||||
Download: "download",
|
||||
EmulatedSizeChanged: "emulatedsizechanged",
|
||||
FileChooser: "filechooser",
|
||||
FrameAttached: "frameattached",
|
||||
FrameDetached: "framedetached",
|
||||
InternalFrameNavigatedToNewDocument: "internalframenavigatedtonewdocument",
|
||||
LocatorHandlerTriggered: "locatorhandlertriggered",
|
||||
ScreencastFrame: "screencastframe",
|
||||
Video: "video",
|
||||
WebSocket: "websocket",
|
||||
Worker: "worker"
|
||||
};
|
||||
this.Events = PageEvent;
|
||||
}
|
||||
async reportAsNew(opener, error) {
|
||||
if (opener) {
|
||||
@@ -158,17 +159,17 @@ class Page extends import_instrumentation.SdkObject {
|
||||
}
|
||||
_didClose() {
|
||||
this.frameManager.dispose();
|
||||
this._frameThrottler.dispose();
|
||||
this.screencast.stopFrameThrottler();
|
||||
(0, import_utils.assert)(this._closedState !== "closed", "Page closed twice");
|
||||
this._closedState = "closed";
|
||||
this.emit(Page.Events.Close);
|
||||
this._closedPromise.resolve();
|
||||
this.instrumentation.onPageClose(this);
|
||||
this.openScope.close(new import_errors.TargetClosedError());
|
||||
this.openScope.close(new import_errors.TargetClosedError(this.closeReason()));
|
||||
}
|
||||
_didCrash() {
|
||||
this.frameManager.dispose();
|
||||
this._frameThrottler.dispose();
|
||||
this.screencast.stopFrameThrottler();
|
||||
this.emit(Page.Events.Crash);
|
||||
this._crashed = true;
|
||||
this.instrumentation.onPageClose(this);
|
||||
@@ -578,7 +579,7 @@ class Page extends import_instrumentation.SdkObject {
|
||||
if (this._closedState === "closed")
|
||||
return;
|
||||
if (options.reason)
|
||||
this.closeReason = options.reason;
|
||||
this._closeReason = options.reason;
|
||||
const runBeforeUnload = !!options.runBeforeUnload;
|
||||
if (this._closedState !== "closing") {
|
||||
if (!runBeforeUnload)
|
||||
@@ -641,16 +642,6 @@ class Page extends import_instrumentation.SdkObject {
|
||||
getBinding(name) {
|
||||
return this._pageBindings.get(name) || this.browserContext._pageBindings.get(name);
|
||||
}
|
||||
setScreencastOptions(options) {
|
||||
this.delegate.setScreencastOptions(options).catch((e) => import_debugLogger.debugLogger.log("error", e));
|
||||
this._frameThrottler.setThrottlingEnabled(!!options);
|
||||
}
|
||||
throttleScreencastFrameAck(ack) {
|
||||
this._frameThrottler.ack(ack);
|
||||
}
|
||||
temporarilyDisableTracingScreencastThrottling() {
|
||||
this._frameThrottler.recharge();
|
||||
}
|
||||
async safeNonStallingEvaluateInAllFrames(expression, world, options = {}) {
|
||||
await Promise.all(this.frames().map(async (frame) => {
|
||||
try {
|
||||
@@ -665,11 +656,14 @@ class Page extends import_instrumentation.SdkObject {
|
||||
await Promise.all(this.frames().map((frame) => frame.hideHighlight().catch(() => {
|
||||
})));
|
||||
}
|
||||
async snapshotForAI(progress, options) {
|
||||
async snapshotForAI(progress, options = {}) {
|
||||
const snapshot = await snapshotFrameForAI(progress, this.mainFrame(), options);
|
||||
return { full: snapshot.full.join("\n"), incremental: snapshot.incremental?.join("\n") };
|
||||
}
|
||||
}
|
||||
const WorkerEvent = {
|
||||
Close: "close"
|
||||
};
|
||||
class Worker extends import_instrumentation.SdkObject {
|
||||
constructor(parent, url) {
|
||||
super(parent, "worker");
|
||||
@@ -680,9 +674,7 @@ class Worker extends import_instrumentation.SdkObject {
|
||||
this.url = url;
|
||||
}
|
||||
static {
|
||||
this.Events = {
|
||||
Close: "close"
|
||||
};
|
||||
this.Events = WorkerEvent;
|
||||
}
|
||||
createExecutionContext(delegate) {
|
||||
this.existingExecutionContext = new js.ExecutionContext(this, delegate, "worker");
|
||||
@@ -763,56 +755,7 @@ class InitScript {
|
||||
})();`;
|
||||
}
|
||||
}
|
||||
class FrameThrottler {
|
||||
constructor(nonThrottledFrames, defaultInterval, throttlingInterval) {
|
||||
this._acks = [];
|
||||
this._throttlingEnabled = false;
|
||||
this._nonThrottledFrames = nonThrottledFrames;
|
||||
this._budget = nonThrottledFrames;
|
||||
this._defaultInterval = defaultInterval;
|
||||
this._throttlingInterval = throttlingInterval;
|
||||
this._tick();
|
||||
}
|
||||
dispose() {
|
||||
if (this._timeoutId) {
|
||||
clearTimeout(this._timeoutId);
|
||||
this._timeoutId = void 0;
|
||||
}
|
||||
}
|
||||
setThrottlingEnabled(enabled) {
|
||||
this._throttlingEnabled = enabled;
|
||||
}
|
||||
recharge() {
|
||||
for (const ack of this._acks)
|
||||
ack();
|
||||
this._acks = [];
|
||||
this._budget = this._nonThrottledFrames;
|
||||
if (this._timeoutId) {
|
||||
clearTimeout(this._timeoutId);
|
||||
this._tick();
|
||||
}
|
||||
}
|
||||
ack(ack) {
|
||||
if (!this._timeoutId) {
|
||||
ack();
|
||||
return;
|
||||
}
|
||||
this._acks.push(ack);
|
||||
}
|
||||
_tick() {
|
||||
const ack = this._acks.shift();
|
||||
if (ack) {
|
||||
--this._budget;
|
||||
ack();
|
||||
}
|
||||
if (this._throttlingEnabled && this._budget <= 0) {
|
||||
this._timeoutId = setTimeout(() => this._tick(), this._throttlingInterval);
|
||||
} else {
|
||||
this._timeoutId = setTimeout(() => this._tick(), this._defaultInterval);
|
||||
}
|
||||
}
|
||||
}
|
||||
async function snapshotFrameForAI(progress, frame, options) {
|
||||
async function snapshotFrameForAI(progress, frame, options = {}) {
|
||||
const snapshot = await frame.retryWithProgressAndTimeouts(progress, [1e3, 2e3, 4e3, 8e3], async (continuePolling) => {
|
||||
try {
|
||||
const context = await progress.race(frame._utilityContext());
|
||||
@@ -822,7 +765,7 @@ async function snapshotFrameForAI(progress, frame, options) {
|
||||
if (!node)
|
||||
return true;
|
||||
return injected.incrementalAriaSnapshot(node, { mode: "ai", ...options2 });
|
||||
}, { refPrefix: frame.seq ? "f" + frame.seq : "", track: options.track }));
|
||||
}, { refPrefix: frame.seq ? "f" + frame.seq : "", track: options.track, doNotRenderActive: options.doNotRenderActive }));
|
||||
if (snapshotOrRetry === true)
|
||||
return continuePolling;
|
||||
return snapshotOrRetry;
|
||||
@@ -882,5 +825,6 @@ function ensureArrayLimit(array, limit) {
|
||||
InitScript,
|
||||
Page,
|
||||
PageBinding,
|
||||
Worker
|
||||
Worker,
|
||||
WorkerEvent
|
||||
});
|
||||
|
||||
32
node_modules/playwright-core/lib/server/progress.js
generated
vendored
32
node_modules/playwright-core/lib/server/progress.js
generated
vendored
@@ -34,19 +34,35 @@ class ProgressController {
|
||||
this.metadata = metadata || { id: "", startTime: 0, endTime: 0, type: "Internal", method: "", params: {}, log: [], internal: true };
|
||||
this._onCallLog = onCallLog;
|
||||
this._forceAbortPromise.catch((e) => null);
|
||||
this._controller = new AbortController();
|
||||
}
|
||||
static createForSdkObject(sdkObject, callMetadata) {
|
||||
const logName = sdkObject.logName || "api";
|
||||
return new ProgressController(callMetadata, (message) => {
|
||||
import_utils.debugLogger.log(logName, message);
|
||||
sdkObject.instrumentation.onCallLog(sdkObject, callMetadata, logName, message);
|
||||
});
|
||||
}
|
||||
async abort(error) {
|
||||
if (this._state === "running") {
|
||||
error[kAbortErrorSymbol] = true;
|
||||
this._state = { error };
|
||||
this._forceAbortPromise.reject(error);
|
||||
this._controller.abort(error);
|
||||
}
|
||||
await this._donePromise;
|
||||
}
|
||||
async run(task, timeout) {
|
||||
const deadline = timeout ? (0, import_utils.monotonicTime)() + timeout : 0;
|
||||
(0, import_utils.assert)(this._state === "before");
|
||||
this._state = "running";
|
||||
let timer;
|
||||
const progress = {
|
||||
timeout: timeout ?? 0,
|
||||
deadline,
|
||||
disableTimeout: () => {
|
||||
clearTimeout(timer);
|
||||
},
|
||||
log: (message) => {
|
||||
if (this._state === "running")
|
||||
this.metadata.log.push(message);
|
||||
@@ -55,24 +71,28 @@ class ProgressController {
|
||||
metadata: this.metadata,
|
||||
race: (promise) => {
|
||||
const promises = Array.isArray(promise) ? promise : [promise];
|
||||
if (!promises.length)
|
||||
return Promise.resolve();
|
||||
return Promise.race([...promises, this._forceAbortPromise]);
|
||||
},
|
||||
wait: async (timeout2) => {
|
||||
let timer2;
|
||||
const promise = new Promise((f) => timer2 = setTimeout(f, timeout2));
|
||||
return progress.race(promise).finally(() => clearTimeout(timer2));
|
||||
}
|
||||
},
|
||||
signal: this._controller.signal
|
||||
};
|
||||
let timer;
|
||||
if (timeout) {
|
||||
if (deadline) {
|
||||
const timeoutError = new import_errors.TimeoutError(`Timeout ${timeout}ms exceeded.`);
|
||||
timer = setTimeout(() => {
|
||||
if (this.metadata.pauseStartTime && !this.metadata.pauseEndTime)
|
||||
return;
|
||||
if (this._state === "running") {
|
||||
timeoutError[kAbortErrorSymbol] = true;
|
||||
this._state = { error: timeoutError };
|
||||
this._forceAbortPromise.reject(timeoutError);
|
||||
this._controller.abort(timeoutError);
|
||||
}
|
||||
}, timeout);
|
||||
}, deadline - (0, import_utils.monotonicTime)());
|
||||
}
|
||||
try {
|
||||
const result = await task(progress);
|
||||
@@ -89,7 +109,7 @@ class ProgressController {
|
||||
}
|
||||
const kAbortErrorSymbol = Symbol("kAbortError");
|
||||
function isAbortError(error) {
|
||||
return !!error[kAbortErrorSymbol];
|
||||
return error instanceof import_errors.TimeoutError || !!error[kAbortErrorSymbol];
|
||||
}
|
||||
async function raceUncancellableOperationWithCleanup(progress, run, cleanup) {
|
||||
let aborted = false;
|
||||
|
||||
179
node_modules/playwright-core/lib/server/recorder/recorderApp.js
generated
vendored
179
node_modules/playwright-core/lib/server/recorder/recorderApp.js
generated
vendored
@@ -53,6 +53,7 @@ class RecorderApp {
|
||||
this._recorderSources = [];
|
||||
this._page = page;
|
||||
this._recorder = recorder;
|
||||
this._frontend = createRecorderFrontend(page);
|
||||
this.wsEndpointForTest = wsEndpointForTest;
|
||||
this._languageGeneratorOptions = {
|
||||
browserName: params.browserName,
|
||||
@@ -64,6 +65,10 @@ class RecorderApp {
|
||||
this._throttledOutputFile = params.outputFile ? new import_throttledFile.ThrottledFile(params.outputFile) : null;
|
||||
this._primaryGeneratorId = process.env.TEST_INSPECTOR_LANGUAGE || params.language || determinePrimaryGeneratorId(params.sdkLanguage);
|
||||
this._selectedGeneratorId = this._primaryGeneratorId;
|
||||
for (const languageGenerator of (0, import_languages.languageSet)()) {
|
||||
if (languageGenerator.id === this._primaryGeneratorId)
|
||||
this._recorder.setLanguage(languageGenerator.highlighter);
|
||||
}
|
||||
}
|
||||
async _init(inspectedContext) {
|
||||
await (0, import_launchApp.syncLocalStorageWithSettings)(this._page, "recorder");
|
||||
@@ -89,7 +94,7 @@ class RecorderApp {
|
||||
});
|
||||
});
|
||||
});
|
||||
await this._page.exposeBinding(progress, "dispatch", false, (_, data) => this._handleUIEvent(data));
|
||||
await this._createDispatcher(progress);
|
||||
this._page.once("close", () => {
|
||||
this._recorder.close();
|
||||
this._page.browserContext.close({ reason: "Recorder window closed" }).catch(() => {
|
||||
@@ -100,59 +105,56 @@ class RecorderApp {
|
||||
});
|
||||
const url = this._recorder.url();
|
||||
if (url)
|
||||
this._onPageNavigated(url);
|
||||
this._onModeChanged(this._recorder.mode());
|
||||
this._onPausedStateChanged(this._recorder.paused());
|
||||
this._frontend.pageNavigated({ url });
|
||||
this._frontend.modeChanged({ mode: this._recorder.mode() });
|
||||
this._frontend.pauseStateChanged({ paused: this._recorder.paused() });
|
||||
this._updateActions("reveal");
|
||||
this._onUserSourcesChanged(this._recorder.userSources(), this._recorder.pausedSourceId());
|
||||
this._onCallLogsUpdated(this._recorder.callLog());
|
||||
this._frontend.callLogsUpdated({ callLogs: this._recorder.callLog() });
|
||||
this._wireListeners(this._recorder);
|
||||
}
|
||||
_handleUIEvent(data) {
|
||||
if (data.event === "clear") {
|
||||
this._actions = [];
|
||||
this._updateActions("reveal");
|
||||
this._recorder.clear();
|
||||
return;
|
||||
}
|
||||
if (data.event === "fileChanged") {
|
||||
const source = [...this._recorderSources, ...this._userSources].find((s) => s.id === data.params.fileId);
|
||||
if (source) {
|
||||
if (source.isRecorded)
|
||||
this._selectedGeneratorId = source.id;
|
||||
this._recorder.setLanguage(source.language);
|
||||
async _createDispatcher(progress) {
|
||||
const dispatcher = {
|
||||
clear: async () => {
|
||||
this._actions = [];
|
||||
this._updateActions("reveal");
|
||||
this._recorder.clear();
|
||||
},
|
||||
fileChanged: async (params) => {
|
||||
const source = [...this._recorderSources, ...this._userSources].find((s) => s.id === params.fileId);
|
||||
if (source) {
|
||||
if (source.isRecorded)
|
||||
this._selectedGeneratorId = source.id;
|
||||
this._recorder.setLanguage(source.language);
|
||||
}
|
||||
},
|
||||
setAutoExpect: async (params) => {
|
||||
this._languageGeneratorOptions.generateAutoExpect = params.autoExpect;
|
||||
this._updateActions();
|
||||
},
|
||||
setMode: async (params) => {
|
||||
this._recorder.setMode(params.mode);
|
||||
},
|
||||
resume: async () => {
|
||||
this._recorder.resume();
|
||||
},
|
||||
pause: async () => {
|
||||
this._recorder.pause();
|
||||
},
|
||||
step: async () => {
|
||||
this._recorder.step();
|
||||
},
|
||||
highlightRequested: async (params) => {
|
||||
if (params.selector)
|
||||
this._recorder.setHighlightedSelector(params.selector);
|
||||
if (params.ariaTemplate)
|
||||
this._recorder.setHighlightedAriaTemplate(params.ariaTemplate);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (data.event === "setAutoExpect") {
|
||||
this._languageGeneratorOptions.generateAutoExpect = data.params.autoExpect;
|
||||
this._updateActions();
|
||||
return;
|
||||
}
|
||||
if (data.event === "setMode") {
|
||||
this._recorder.setMode(data.params.mode);
|
||||
return;
|
||||
}
|
||||
if (data.event === "resume") {
|
||||
this._recorder.resume();
|
||||
return;
|
||||
}
|
||||
if (data.event === "pause") {
|
||||
this._recorder.pause();
|
||||
return;
|
||||
}
|
||||
if (data.event === "step") {
|
||||
this._recorder.step();
|
||||
return;
|
||||
}
|
||||
if (data.event === "highlightRequested") {
|
||||
if (data.params.selector)
|
||||
this._recorder.setHighlightedSelector(data.params.selector);
|
||||
if (data.params.ariaTemplate)
|
||||
this._recorder.setHighlightedAriaTemplate(data.params.ariaTemplate);
|
||||
return;
|
||||
}
|
||||
throw new Error(`Unknown event: ${data.event}`);
|
||||
};
|
||||
await this._page.exposeBinding(progress, "sendCommand", false, async (_, data) => {
|
||||
const { method, params } = data;
|
||||
return await dispatcher[method].call(dispatcher, params);
|
||||
});
|
||||
}
|
||||
static async show(context, params) {
|
||||
if (process.env.PW_CODEGEN_NO_INSPECTOR)
|
||||
@@ -220,25 +222,29 @@ class RecorderApp {
|
||||
this._onSignalAdded(signal);
|
||||
});
|
||||
recorder.on(import_recorder.RecorderEvent.PageNavigated, (url) => {
|
||||
this._onPageNavigated(url);
|
||||
this._frontend.pageNavigated({ url });
|
||||
});
|
||||
recorder.on(import_recorder.RecorderEvent.ContextClosed, () => {
|
||||
this._onContextClosed();
|
||||
this._throttledOutputFile?.flush();
|
||||
this._page.browserContext.close({ reason: "Recorder window closed" }).catch(() => {
|
||||
});
|
||||
});
|
||||
recorder.on(import_recorder.RecorderEvent.ModeChanged, (mode) => {
|
||||
this._onModeChanged(mode);
|
||||
this._frontend.modeChanged({ mode });
|
||||
});
|
||||
recorder.on(import_recorder.RecorderEvent.PausedStateChanged, (paused) => {
|
||||
this._onPausedStateChanged(paused);
|
||||
this._frontend.pauseStateChanged({ paused });
|
||||
});
|
||||
recorder.on(import_recorder.RecorderEvent.UserSourcesChanged, (sources, pausedSourceId) => {
|
||||
this._onUserSourcesChanged(sources, pausedSourceId);
|
||||
});
|
||||
recorder.on(import_recorder.RecorderEvent.ElementPicked, (elementInfo, userGesture) => {
|
||||
this._onElementPicked(elementInfo, userGesture);
|
||||
if (userGesture)
|
||||
this._page.bringToFront();
|
||||
this._frontend.elementPicked({ elementInfo, userGesture });
|
||||
});
|
||||
recorder.on(import_recorder.RecorderEvent.CallLogsUpdated, (callLogs) => {
|
||||
this._onCallLogsUpdated(callLogs);
|
||||
this._frontend.callLogsUpdated({ callLogs });
|
||||
});
|
||||
}
|
||||
_onActionAdded(action) {
|
||||
@@ -251,29 +257,6 @@ class RecorderApp {
|
||||
lastAction.action.signals.push(signal.signal);
|
||||
this._updateActions();
|
||||
}
|
||||
_onPageNavigated(url) {
|
||||
this._page.mainFrame().evaluateExpression((({ url: url2 }) => {
|
||||
window.playwrightSetPageURL(url2);
|
||||
}).toString(), { isFunction: true }, { url }).catch(() => {
|
||||
});
|
||||
}
|
||||
_onContextClosed() {
|
||||
this._throttledOutputFile?.flush();
|
||||
this._page.browserContext.close({ reason: "Recorder window closed" }).catch(() => {
|
||||
});
|
||||
}
|
||||
_onModeChanged(mode) {
|
||||
this._page.mainFrame().evaluateExpression(((mode2) => {
|
||||
window.playwrightSetMode(mode2);
|
||||
}).toString(), { isFunction: true }, mode).catch(() => {
|
||||
});
|
||||
}
|
||||
_onPausedStateChanged(paused) {
|
||||
this._page.mainFrame().evaluateExpression(((paused2) => {
|
||||
window.playwrightSetPaused(paused2);
|
||||
}).toString(), { isFunction: true }, paused).catch(() => {
|
||||
});
|
||||
}
|
||||
_onUserSourcesChanged(sources, pausedSourceId) {
|
||||
if (!sources.length && !this._userSources.length)
|
||||
return;
|
||||
@@ -281,34 +264,14 @@ class RecorderApp {
|
||||
this._pushAllSources();
|
||||
this._revealSource(pausedSourceId);
|
||||
}
|
||||
_onElementPicked(elementInfo, userGesture) {
|
||||
if (userGesture)
|
||||
this._page.bringToFront();
|
||||
this._page.mainFrame().evaluateExpression(((param) => {
|
||||
window.playwrightElementPicked(param.elementInfo, param.userGesture);
|
||||
}).toString(), { isFunction: true }, { elementInfo, userGesture }).catch(() => {
|
||||
});
|
||||
}
|
||||
_onCallLogsUpdated(callLogs) {
|
||||
this._page.mainFrame().evaluateExpression(((callLogs2) => {
|
||||
window.playwrightUpdateLogs(callLogs2);
|
||||
}).toString(), { isFunction: true }, callLogs).catch(() => {
|
||||
});
|
||||
}
|
||||
_pushAllSources() {
|
||||
const sources = [...this._userSources, ...this._recorderSources];
|
||||
this._page.mainFrame().evaluateExpression((({ sources: sources2 }) => {
|
||||
window.playwrightSetSources(sources2);
|
||||
}).toString(), { isFunction: true }, { sources }).catch(() => {
|
||||
});
|
||||
this._frontend.sourcesUpdated({ sources });
|
||||
}
|
||||
_revealSource(sourceId) {
|
||||
if (!sourceId)
|
||||
return;
|
||||
this._page.mainFrame().evaluateExpression((({ sourceId: sourceId2 }) => {
|
||||
window.playwrightSelectSource(sourceId2);
|
||||
}).toString(), { isFunction: true }, { sourceId }).catch(() => {
|
||||
});
|
||||
this._frontend.sourceRevealRequested({ sourceId });
|
||||
}
|
||||
_updateActions(reveal) {
|
||||
const recorderSources = [];
|
||||
@@ -372,6 +335,8 @@ class ProgrammaticRecorderApp {
|
||||
});
|
||||
recorder.on(import_recorder.RecorderEvent.SignalAdded, (signal) => {
|
||||
const page = findPageByGuid(inspectedContext, signal.frame.pageGuid);
|
||||
if (!page)
|
||||
return;
|
||||
inspectedContext.emit(import_browserContext.BrowserContext.Events.RecorderEvent, { event: "signalAdded", data: signal, page, code: "" });
|
||||
});
|
||||
}
|
||||
@@ -379,6 +344,20 @@ class ProgrammaticRecorderApp {
|
||||
function findPageByGuid(context, guid) {
|
||||
return context.pages().find((p) => p.guid === guid);
|
||||
}
|
||||
function createRecorderFrontend(page) {
|
||||
return new Proxy({}, {
|
||||
get: (_target, prop) => {
|
||||
if (typeof prop !== "string")
|
||||
return void 0;
|
||||
return (params) => {
|
||||
page.mainFrame().evaluateExpression(((event) => {
|
||||
window.dispatch(event);
|
||||
}).toString(), { isFunction: true }, { method: prop, params }).catch(() => {
|
||||
});
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
const recorderAppSymbol = Symbol("recorderApp");
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
|
||||
10
node_modules/playwright-core/lib/server/registry/browserFetcher.js
generated
vendored
10
node_modules/playwright-core/lib/server/registry/browserFetcher.js
generated
vendored
@@ -42,10 +42,13 @@ var import_userAgent = require("../utils/userAgent");
|
||||
var import_utilsBundle = require("../../utilsBundle");
|
||||
var import_fileUtils = require("../utils/fileUtils");
|
||||
var import__ = require(".");
|
||||
async function downloadBrowserWithProgressBar(title, browserDirectory, executablePath, downloadURLs, downloadFileName, downloadSocketTimeout) {
|
||||
async function downloadBrowserWithProgressBar(title, browserDirectory, executablePath, downloadURLs, downloadFileName, downloadSocketTimeout, force) {
|
||||
if (await (0, import_fileUtils.existsAsync)((0, import__.browserDirectoryToMarkerFilePath)(browserDirectory))) {
|
||||
import_debugLogger.debugLogger.log("install", `${title} is already downloaded.`);
|
||||
return false;
|
||||
if (force)
|
||||
import_debugLogger.debugLogger.log("install", `force-downloading ${title}.`);
|
||||
else
|
||||
return;
|
||||
}
|
||||
const uniqueTempDir = await import_fs.default.promises.mkdtemp(import_path.default.join(import_os.default.tmpdir(), "playwright-download-"));
|
||||
const zipPath = import_path.default.join(uniqueTempDir, downloadFileName);
|
||||
@@ -63,7 +66,7 @@ async function downloadBrowserWithProgressBar(title, browserDirectory, executabl
|
||||
if (await (0, import_fileUtils.existsAsync)(zipPath))
|
||||
await import_fs.default.promises.unlink(zipPath);
|
||||
if (await (0, import_fileUtils.existsAsync)(browserDirectory))
|
||||
await import_fs.default.promises.rmdir(browserDirectory, { recursive: true });
|
||||
await (0, import_fileUtils.removeFolders)([browserDirectory]);
|
||||
const errorMessage = error?.message || "";
|
||||
import_debugLogger.debugLogger.log("install", `attempt #${attempt} - ERROR: ${errorMessage}`);
|
||||
if (attempt >= retryCount)
|
||||
@@ -77,7 +80,6 @@ async function downloadBrowserWithProgressBar(title, browserDirectory, executabl
|
||||
await (0, import_fileUtils.removeFolders)([uniqueTempDir]);
|
||||
}
|
||||
logPolitely(`${title} downloaded to ${browserDirectory}`);
|
||||
return true;
|
||||
}
|
||||
function downloadBrowserWithProgressBarOutOfProcess(title, browserDirectory, url, zipPath, executablePath, socketTimeout) {
|
||||
const cp = childProcess.fork(import_path.default.join(__dirname, "oopDownloadBrowserMain.js"));
|
||||
|
||||
321
node_modules/playwright-core/lib/server/registry/index.js
generated
vendored
321
node_modules/playwright-core/lib/server/registry/index.js
generated
vendored
@@ -145,130 +145,140 @@ const EXECUTABLE_PATHS = {
|
||||
"win-x64": ["PrintDeps.exe"]
|
||||
}
|
||||
};
|
||||
function cftUrl(suffix) {
|
||||
return ({ browserVersion }) => {
|
||||
return {
|
||||
path: `builds/cft/${browserVersion}/${suffix}`,
|
||||
mirrors: [
|
||||
"https://cdn.playwright.dev"
|
||||
]
|
||||
};
|
||||
};
|
||||
}
|
||||
const DOWNLOAD_PATHS = {
|
||||
"chromium": {
|
||||
"<unknown>": void 0,
|
||||
"ubuntu18.04-x64": void 0,
|
||||
"ubuntu20.04-x64": "builds/chromium/%s/chromium-linux.zip",
|
||||
"ubuntu22.04-x64": "builds/chromium/%s/chromium-linux.zip",
|
||||
"ubuntu24.04-x64": "builds/chromium/%s/chromium-linux.zip",
|
||||
"ubuntu20.04-x64": cftUrl("linux64/chrome-linux64.zip"),
|
||||
"ubuntu22.04-x64": cftUrl("linux64/chrome-linux64.zip"),
|
||||
"ubuntu24.04-x64": cftUrl("linux64/chrome-linux64.zip"),
|
||||
"ubuntu18.04-arm64": void 0,
|
||||
"ubuntu20.04-arm64": "builds/chromium/%s/chromium-linux-arm64.zip",
|
||||
"ubuntu22.04-arm64": "builds/chromium/%s/chromium-linux-arm64.zip",
|
||||
"ubuntu24.04-arm64": "builds/chromium/%s/chromium-linux-arm64.zip",
|
||||
"debian11-x64": "builds/chromium/%s/chromium-linux.zip",
|
||||
"debian11-x64": cftUrl("linux64/chrome-linux64.zip"),
|
||||
"debian11-arm64": "builds/chromium/%s/chromium-linux-arm64.zip",
|
||||
"debian12-x64": "builds/chromium/%s/chromium-linux.zip",
|
||||
"debian12-x64": cftUrl("linux64/chrome-linux64.zip"),
|
||||
"debian12-arm64": "builds/chromium/%s/chromium-linux-arm64.zip",
|
||||
"debian13-x64": "builds/chromium/%s/chromium-linux.zip",
|
||||
"debian13-x64": cftUrl("linux64/chrome-linux64.zip"),
|
||||
"debian13-arm64": "builds/chromium/%s/chromium-linux-arm64.zip",
|
||||
"mac10.13": "builds/chromium/%s/chromium-mac.zip",
|
||||
"mac10.14": "builds/chromium/%s/chromium-mac.zip",
|
||||
"mac10.15": "builds/chromium/%s/chromium-mac.zip",
|
||||
"mac11": "builds/chromium/%s/chromium-mac.zip",
|
||||
"mac11-arm64": "builds/chromium/%s/chromium-mac-arm64.zip",
|
||||
"mac12": "builds/chromium/%s/chromium-mac.zip",
|
||||
"mac12-arm64": "builds/chromium/%s/chromium-mac-arm64.zip",
|
||||
"mac13": "builds/chromium/%s/chromium-mac.zip",
|
||||
"mac13-arm64": "builds/chromium/%s/chromium-mac-arm64.zip",
|
||||
"mac14": "builds/chromium/%s/chromium-mac.zip",
|
||||
"mac14-arm64": "builds/chromium/%s/chromium-mac-arm64.zip",
|
||||
"mac15": "builds/chromium/%s/chromium-mac.zip",
|
||||
"mac15-arm64": "builds/chromium/%s/chromium-mac-arm64.zip",
|
||||
"win64": "builds/chromium/%s/chromium-win64.zip"
|
||||
"mac10.13": cftUrl("mac-x64/chrome-mac-x64.zip"),
|
||||
"mac10.14": cftUrl("mac-x64/chrome-mac-x64.zip"),
|
||||
"mac10.15": cftUrl("mac-x64/chrome-mac-x64.zip"),
|
||||
"mac11": cftUrl("mac-x64/chrome-mac-x64.zip"),
|
||||
"mac11-arm64": cftUrl("mac-arm64/chrome-mac-arm64.zip"),
|
||||
"mac12": cftUrl("mac-x64/chrome-mac-x64.zip"),
|
||||
"mac12-arm64": cftUrl("mac-arm64/chrome-mac-arm64.zip"),
|
||||
"mac13": cftUrl("mac-x64/chrome-mac-x64.zip"),
|
||||
"mac13-arm64": cftUrl("mac-arm64/chrome-mac-arm64.zip"),
|
||||
"mac14": cftUrl("mac-x64/chrome-mac-x64.zip"),
|
||||
"mac14-arm64": cftUrl("mac-arm64/chrome-mac-arm64.zip"),
|
||||
"mac15": cftUrl("mac-x64/chrome-mac-x64.zip"),
|
||||
"mac15-arm64": cftUrl("mac-arm64/chrome-mac-arm64.zip"),
|
||||
"win64": cftUrl("win64/chrome-win64.zip")
|
||||
},
|
||||
"chromium-headless-shell": {
|
||||
"<unknown>": void 0,
|
||||
"ubuntu18.04-x64": void 0,
|
||||
"ubuntu20.04-x64": "builds/chromium/%s/chromium-headless-shell-linux.zip",
|
||||
"ubuntu22.04-x64": "builds/chromium/%s/chromium-headless-shell-linux.zip",
|
||||
"ubuntu24.04-x64": "builds/chromium/%s/chromium-headless-shell-linux.zip",
|
||||
"ubuntu20.04-x64": cftUrl("linux64/chrome-headless-shell-linux64.zip"),
|
||||
"ubuntu22.04-x64": cftUrl("linux64/chrome-headless-shell-linux64.zip"),
|
||||
"ubuntu24.04-x64": cftUrl("linux64/chrome-headless-shell-linux64.zip"),
|
||||
"ubuntu18.04-arm64": void 0,
|
||||
"ubuntu20.04-arm64": "builds/chromium/%s/chromium-headless-shell-linux-arm64.zip",
|
||||
"ubuntu22.04-arm64": "builds/chromium/%s/chromium-headless-shell-linux-arm64.zip",
|
||||
"ubuntu24.04-arm64": "builds/chromium/%s/chromium-headless-shell-linux-arm64.zip",
|
||||
"debian11-x64": "builds/chromium/%s/chromium-headless-shell-linux.zip",
|
||||
"debian11-x64": cftUrl("linux64/chrome-headless-shell-linux64.zip"),
|
||||
"debian11-arm64": "builds/chromium/%s/chromium-headless-shell-linux-arm64.zip",
|
||||
"debian12-x64": "builds/chromium/%s/chromium-headless-shell-linux.zip",
|
||||
"debian12-x64": cftUrl("linux64/chrome-headless-shell-linux64.zip"),
|
||||
"debian12-arm64": "builds/chromium/%s/chromium-headless-shell-linux-arm64.zip",
|
||||
"debian13-x64": "builds/chromium/%s/chromium-headless-shell-linux.zip",
|
||||
"debian13-x64": cftUrl("linux64/chrome-headless-shell-linux64.zip"),
|
||||
"debian13-arm64": "builds/chromium/%s/chromium-headless-shell-linux-arm64.zip",
|
||||
"mac10.13": void 0,
|
||||
"mac10.14": void 0,
|
||||
"mac10.15": void 0,
|
||||
"mac11": "builds/chromium/%s/chromium-headless-shell-mac.zip",
|
||||
"mac11-arm64": "builds/chromium/%s/chromium-headless-shell-mac-arm64.zip",
|
||||
"mac12": "builds/chromium/%s/chromium-headless-shell-mac.zip",
|
||||
"mac12-arm64": "builds/chromium/%s/chromium-headless-shell-mac-arm64.zip",
|
||||
"mac13": "builds/chromium/%s/chromium-headless-shell-mac.zip",
|
||||
"mac13-arm64": "builds/chromium/%s/chromium-headless-shell-mac-arm64.zip",
|
||||
"mac14": "builds/chromium/%s/chromium-headless-shell-mac.zip",
|
||||
"mac14-arm64": "builds/chromium/%s/chromium-headless-shell-mac-arm64.zip",
|
||||
"mac15": "builds/chromium/%s/chromium-headless-shell-mac.zip",
|
||||
"mac15-arm64": "builds/chromium/%s/chromium-headless-shell-mac-arm64.zip",
|
||||
"win64": "builds/chromium/%s/chromium-headless-shell-win64.zip"
|
||||
"mac11": cftUrl("mac-x64/chrome-headless-shell-mac-x64.zip"),
|
||||
"mac11-arm64": cftUrl("mac-arm64/chrome-headless-shell-mac-arm64.zip"),
|
||||
"mac12": cftUrl("mac-x64/chrome-headless-shell-mac-x64.zip"),
|
||||
"mac12-arm64": cftUrl("mac-arm64/chrome-headless-shell-mac-arm64.zip"),
|
||||
"mac13": cftUrl("mac-x64/chrome-headless-shell-mac-x64.zip"),
|
||||
"mac13-arm64": cftUrl("mac-arm64/chrome-headless-shell-mac-arm64.zip"),
|
||||
"mac14": cftUrl("mac-x64/chrome-headless-shell-mac-x64.zip"),
|
||||
"mac14-arm64": cftUrl("mac-arm64/chrome-headless-shell-mac-arm64.zip"),
|
||||
"mac15": cftUrl("mac-x64/chrome-headless-shell-mac-x64.zip"),
|
||||
"mac15-arm64": cftUrl("mac-arm64/chrome-headless-shell-mac-arm64.zip"),
|
||||
"win64": cftUrl("win64/chrome-headless-shell-win64.zip")
|
||||
},
|
||||
"chromium-tip-of-tree": {
|
||||
"<unknown>": void 0,
|
||||
"ubuntu18.04-x64": void 0,
|
||||
"ubuntu20.04-x64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-linux.zip",
|
||||
"ubuntu22.04-x64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-linux.zip",
|
||||
"ubuntu24.04-x64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-linux.zip",
|
||||
"ubuntu20.04-x64": cftUrl("linux64/chrome-linux64.zip"),
|
||||
"ubuntu22.04-x64": cftUrl("linux64/chrome-linux64.zip"),
|
||||
"ubuntu24.04-x64": cftUrl("linux64/chrome-linux64.zip"),
|
||||
"ubuntu18.04-arm64": void 0,
|
||||
"ubuntu20.04-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-linux-arm64.zip",
|
||||
"ubuntu22.04-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-linux-arm64.zip",
|
||||
"ubuntu24.04-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-linux-arm64.zip",
|
||||
"debian11-x64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-linux.zip",
|
||||
"debian11-x64": cftUrl("linux64/chrome-linux64.zip"),
|
||||
"debian11-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-linux-arm64.zip",
|
||||
"debian12-x64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-linux.zip",
|
||||
"debian12-x64": cftUrl("linux64/chrome-linux64.zip"),
|
||||
"debian12-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-linux-arm64.zip",
|
||||
"debian13-x64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-linux.zip",
|
||||
"debian13-x64": cftUrl("linux64/chrome-linux64.zip"),
|
||||
"debian13-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-linux-arm64.zip",
|
||||
"mac10.13": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-mac.zip",
|
||||
"mac10.14": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-mac.zip",
|
||||
"mac10.15": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-mac.zip",
|
||||
"mac11": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-mac.zip",
|
||||
"mac11-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-mac-arm64.zip",
|
||||
"mac12": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-mac.zip",
|
||||
"mac12-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-mac-arm64.zip",
|
||||
"mac13": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-mac.zip",
|
||||
"mac13-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-mac-arm64.zip",
|
||||
"mac14": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-mac.zip",
|
||||
"mac14-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-mac-arm64.zip",
|
||||
"mac15": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-mac.zip",
|
||||
"mac15-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-mac-arm64.zip",
|
||||
"win64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-win64.zip"
|
||||
"mac10.13": cftUrl("mac-x64/chrome-mac-x64.zip"),
|
||||
"mac10.14": cftUrl("mac-x64/chrome-mac-x64.zip"),
|
||||
"mac10.15": cftUrl("mac-x64/chrome-mac-x64.zip"),
|
||||
"mac11": cftUrl("mac-x64/chrome-mac-x64.zip"),
|
||||
"mac11-arm64": cftUrl("mac-arm64/chrome-mac-arm64.zip"),
|
||||
"mac12": cftUrl("mac-x64/chrome-mac-x64.zip"),
|
||||
"mac12-arm64": cftUrl("mac-arm64/chrome-mac-arm64.zip"),
|
||||
"mac13": cftUrl("mac-x64/chrome-mac-x64.zip"),
|
||||
"mac13-arm64": cftUrl("mac-arm64/chrome-mac-arm64.zip"),
|
||||
"mac14": cftUrl("mac-x64/chrome-mac-x64.zip"),
|
||||
"mac14-arm64": cftUrl("mac-arm64/chrome-mac-arm64.zip"),
|
||||
"mac15": cftUrl("mac-x64/chrome-mac-x64.zip"),
|
||||
"mac15-arm64": cftUrl("mac-arm64/chrome-mac-arm64.zip"),
|
||||
"win64": cftUrl("win64/chrome-win64.zip")
|
||||
},
|
||||
"chromium-tip-of-tree-headless-shell": {
|
||||
"<unknown>": void 0,
|
||||
"ubuntu18.04-x64": void 0,
|
||||
"ubuntu20.04-x64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux.zip",
|
||||
"ubuntu22.04-x64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux.zip",
|
||||
"ubuntu24.04-x64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux.zip",
|
||||
"ubuntu20.04-x64": cftUrl("linux64/chrome-headless-shell-linux64.zip"),
|
||||
"ubuntu22.04-x64": cftUrl("linux64/chrome-headless-shell-linux64.zip"),
|
||||
"ubuntu24.04-x64": cftUrl("linux64/chrome-headless-shell-linux64.zip"),
|
||||
"ubuntu18.04-arm64": void 0,
|
||||
"ubuntu20.04-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux-arm64.zip",
|
||||
"ubuntu22.04-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux-arm64.zip",
|
||||
"ubuntu24.04-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux-arm64.zip",
|
||||
"debian11-x64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux.zip",
|
||||
"debian11-x64": cftUrl("linux64/chrome-headless-shell-linux64.zip"),
|
||||
"debian11-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux-arm64.zip",
|
||||
"debian12-x64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux.zip",
|
||||
"debian12-x64": cftUrl("linux64/chrome-headless-shell-linux64.zip"),
|
||||
"debian12-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux-arm64.zip",
|
||||
"debian13-x64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux.zip",
|
||||
"debian13-x64": cftUrl("linux64/chrome-headless-shell-linux64.zip"),
|
||||
"debian13-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux-arm64.zip",
|
||||
"mac10.13": void 0,
|
||||
"mac10.14": void 0,
|
||||
"mac10.15": void 0,
|
||||
"mac11": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac.zip",
|
||||
"mac11-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac-arm64.zip",
|
||||
"mac12": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac.zip",
|
||||
"mac12-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac-arm64.zip",
|
||||
"mac13": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac.zip",
|
||||
"mac13-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac-arm64.zip",
|
||||
"mac14": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac.zip",
|
||||
"mac14-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac-arm64.zip",
|
||||
"mac15": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac.zip",
|
||||
"mac15-arm64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac-arm64.zip",
|
||||
"win64": "builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-win64.zip"
|
||||
"mac11": cftUrl("mac-x64/chrome-headless-shell-mac-x64.zip"),
|
||||
"mac11-arm64": cftUrl("mac-arm64/chrome-headless-shell-mac-arm64.zip"),
|
||||
"mac12": cftUrl("mac-x64/chrome-headless-shell-mac-x64.zip"),
|
||||
"mac12-arm64": cftUrl("mac-arm64/chrome-headless-shell-mac-arm64.zip"),
|
||||
"mac13": cftUrl("mac-x64/chrome-headless-shell-mac-x64.zip"),
|
||||
"mac13-arm64": cftUrl("mac-arm64/chrome-headless-shell-mac-arm64.zip"),
|
||||
"mac14": cftUrl("mac-x64/chrome-headless-shell-mac-x64.zip"),
|
||||
"mac14-arm64": cftUrl("mac-arm64/chrome-headless-shell-mac-arm64.zip"),
|
||||
"mac15": cftUrl("mac-x64/chrome-headless-shell-mac-x64.zip"),
|
||||
"mac15-arm64": cftUrl("mac-arm64/chrome-headless-shell-mac-arm64.zip"),
|
||||
"win64": cftUrl("win64/chrome-headless-shell-win64.zip")
|
||||
},
|
||||
"firefox": {
|
||||
"<unknown>": void 0,
|
||||
@@ -349,14 +359,14 @@ const DOWNLOAD_PATHS = {
|
||||
"debian13-x64": "builds/webkit/%s/webkit-debian-13.zip",
|
||||
"debian13-arm64": "builds/webkit/%s/webkit-debian-13-arm64.zip",
|
||||
"mac10.13": void 0,
|
||||
"mac10.14": "builds/deprecated-webkit-mac-10.14/%s/deprecated-webkit-mac-10.14.zip",
|
||||
"mac10.15": "builds/deprecated-webkit-mac-10.15/%s/deprecated-webkit-mac-10.15.zip",
|
||||
"mac11": "builds/webkit/%s/webkit-mac-11.zip",
|
||||
"mac11-arm64": "builds/webkit/%s/webkit-mac-11-arm64.zip",
|
||||
"mac12": "builds/webkit/%s/webkit-mac-12.zip",
|
||||
"mac12-arm64": "builds/webkit/%s/webkit-mac-12-arm64.zip",
|
||||
"mac13": "builds/webkit/%s/webkit-mac-13.zip",
|
||||
"mac13-arm64": "builds/webkit/%s/webkit-mac-13-arm64.zip",
|
||||
"mac10.14": void 0,
|
||||
"mac10.15": void 0,
|
||||
"mac11": void 0,
|
||||
"mac11-arm64": void 0,
|
||||
"mac12": void 0,
|
||||
"mac12-arm64": void 0,
|
||||
"mac13": void 0,
|
||||
"mac13-arm64": void 0,
|
||||
"mac14": "builds/webkit/%s/webkit-mac-14.zip",
|
||||
"mac14-arm64": "builds/webkit/%s/webkit-mac-14-arm64.zip",
|
||||
"mac15": "builds/webkit/%s/webkit-mac-15.zip",
|
||||
@@ -483,7 +493,7 @@ const registryDirectory = (() => {
|
||||
})();
|
||||
function isBrowserDirectory(browserDirectory) {
|
||||
const baseName = import_path.default.basename(browserDirectory);
|
||||
for (const browserName of allDownloadable) {
|
||||
for (const browserName of allDownloadableDirectoriesThatEverExisted) {
|
||||
if (baseName.startsWith(browserName.replace(/-/g, "_") + "-"))
|
||||
return true;
|
||||
}
|
||||
@@ -501,6 +511,7 @@ function readDescriptors(browsersJSON) {
|
||||
hasRevisionOverride: !!revisionOverride,
|
||||
// We only put browser version for the supported operating systems.
|
||||
browserVersion: revisionOverride ? void 0 : obj.browserVersion,
|
||||
title: obj["title"],
|
||||
installByDefault: !!obj.installByDefault,
|
||||
// Method `isBrowserDirectory` determines directory to be browser iff
|
||||
// it starts with some browser name followed by '-'. Some browser names
|
||||
@@ -512,7 +523,8 @@ function readDescriptors(browsersJSON) {
|
||||
return descriptor;
|
||||
});
|
||||
}
|
||||
const allDownloadable = ["android", "chromium", "firefox", "webkit", "ffmpeg", "firefox-beta", "chromium-tip-of-tree", "chromium-headless-shell", "chromium-tip-of-tree-headless-shell"];
|
||||
const allDownloadableDirectoriesThatEverExisted = ["android", "chromium", "firefox", "webkit", "ffmpeg", "firefox-beta", "chromium-tip-of-tree", "chromium-headless-shell", "chromium-tip-of-tree-headless-shell", "winldd"];
|
||||
const chromiumAliases = ["bidi-chromium", "chrome-for-testing"];
|
||||
class Registry {
|
||||
constructor(browsersJSON) {
|
||||
const descriptors = readDescriptors(browsersJSON);
|
||||
@@ -552,7 +564,6 @@ ${(0, import_ascii.wrapInASCIIBox)(prettyMessage, 1)}`);
|
||||
const chromium = descriptors.find((d) => d.name === "chromium");
|
||||
const chromiumExecutable = findExecutablePath(chromium.dir, "chromium");
|
||||
this._executables.push({
|
||||
type: "browser",
|
||||
name: "chromium",
|
||||
browserName: "chromium",
|
||||
directory: chromium.dir,
|
||||
@@ -561,15 +572,16 @@ ${(0, import_ascii.wrapInASCIIBox)(prettyMessage, 1)}`);
|
||||
installType: chromium.installByDefault ? "download-by-default" : "download-on-demand",
|
||||
_validateHostRequirements: (sdkLanguage) => this._validateHostRequirements(sdkLanguage, chromium.dir, ["chrome-linux"], [], ["chrome-win"]),
|
||||
downloadURLs: this._downloadURLs(chromium),
|
||||
title: chromium.title,
|
||||
revision: chromium.revision,
|
||||
browserVersion: chromium.browserVersion,
|
||||
_install: () => this._downloadExecutable(chromium, chromiumExecutable),
|
||||
_install: (force) => this._downloadExecutable(chromium, force, chromiumExecutable),
|
||||
_dependencyGroup: "chromium",
|
||||
_isHermeticInstallation: true
|
||||
});
|
||||
const chromiumHeadlessShell = descriptors.find((d) => d.name === "chromium-headless-shell");
|
||||
const chromiumHeadlessShellExecutable = findExecutablePath(chromiumHeadlessShell.dir, "chromium-headless-shell");
|
||||
this._executables.push({
|
||||
type: "channel",
|
||||
name: "chromium-headless-shell",
|
||||
browserName: "chromium",
|
||||
directory: chromiumHeadlessShell.dir,
|
||||
@@ -578,15 +590,16 @@ ${(0, import_ascii.wrapInASCIIBox)(prettyMessage, 1)}`);
|
||||
installType: chromiumHeadlessShell.installByDefault ? "download-by-default" : "download-on-demand",
|
||||
_validateHostRequirements: (sdkLanguage) => this._validateHostRequirements(sdkLanguage, chromiumHeadlessShell.dir, ["chrome-linux"], [], ["chrome-win"]),
|
||||
downloadURLs: this._downloadURLs(chromiumHeadlessShell),
|
||||
browserVersion: chromium.browserVersion,
|
||||
_install: () => this._downloadExecutable(chromiumHeadlessShell, chromiumHeadlessShellExecutable),
|
||||
title: chromiumHeadlessShell.title,
|
||||
revision: chromiumHeadlessShell.revision,
|
||||
browserVersion: chromiumHeadlessShell.browserVersion,
|
||||
_install: (force) => this._downloadExecutable(chromiumHeadlessShell, force, chromiumHeadlessShellExecutable),
|
||||
_dependencyGroup: "chromium",
|
||||
_isHermeticInstallation: true
|
||||
});
|
||||
const chromiumTipOfTreeHeadlessShell = descriptors.find((d) => d.name === "chromium-tip-of-tree-headless-shell");
|
||||
const chromiumTipOfTreeHeadlessShellExecutable = findExecutablePath(chromiumTipOfTreeHeadlessShell.dir, "chromium-tip-of-tree-headless-shell");
|
||||
this._executables.push({
|
||||
type: "channel",
|
||||
name: "chromium-tip-of-tree-headless-shell",
|
||||
browserName: "chromium",
|
||||
directory: chromiumTipOfTreeHeadlessShell.dir,
|
||||
@@ -595,15 +608,16 @@ ${(0, import_ascii.wrapInASCIIBox)(prettyMessage, 1)}`);
|
||||
installType: chromiumTipOfTreeHeadlessShell.installByDefault ? "download-by-default" : "download-on-demand",
|
||||
_validateHostRequirements: (sdkLanguage) => this._validateHostRequirements(sdkLanguage, chromiumTipOfTreeHeadlessShell.dir, ["chrome-linux"], [], ["chrome-win"]),
|
||||
downloadURLs: this._downloadURLs(chromiumTipOfTreeHeadlessShell),
|
||||
browserVersion: chromium.browserVersion,
|
||||
_install: () => this._downloadExecutable(chromiumTipOfTreeHeadlessShell, chromiumTipOfTreeHeadlessShellExecutable),
|
||||
title: chromiumTipOfTreeHeadlessShell.title,
|
||||
revision: chromiumTipOfTreeHeadlessShell.revision,
|
||||
browserVersion: chromiumTipOfTreeHeadlessShell.browserVersion,
|
||||
_install: (force) => this._downloadExecutable(chromiumTipOfTreeHeadlessShell, force, chromiumTipOfTreeHeadlessShellExecutable),
|
||||
_dependencyGroup: "chromium",
|
||||
_isHermeticInstallation: true
|
||||
});
|
||||
const chromiumTipOfTree = descriptors.find((d) => d.name === "chromium-tip-of-tree");
|
||||
const chromiumTipOfTreeExecutable = findExecutablePath(chromiumTipOfTree.dir, "chromium-tip-of-tree");
|
||||
this._executables.push({
|
||||
type: "tool",
|
||||
name: "chromium-tip-of-tree",
|
||||
browserName: "chromium",
|
||||
directory: chromiumTipOfTree.dir,
|
||||
@@ -612,8 +626,10 @@ ${(0, import_ascii.wrapInASCIIBox)(prettyMessage, 1)}`);
|
||||
installType: chromiumTipOfTree.installByDefault ? "download-by-default" : "download-on-demand",
|
||||
_validateHostRequirements: (sdkLanguage) => this._validateHostRequirements(sdkLanguage, chromiumTipOfTree.dir, ["chrome-linux"], [], ["chrome-win"]),
|
||||
downloadURLs: this._downloadURLs(chromiumTipOfTree),
|
||||
title: chromiumTipOfTree.title,
|
||||
revision: chromiumTipOfTree.revision,
|
||||
browserVersion: chromiumTipOfTree.browserVersion,
|
||||
_install: () => this._downloadExecutable(chromiumTipOfTree, chromiumTipOfTreeExecutable),
|
||||
_install: (force) => this._downloadExecutable(chromiumTipOfTree, force, chromiumTipOfTreeExecutable),
|
||||
_dependencyGroup: "chromium",
|
||||
_isHermeticInstallation: true
|
||||
});
|
||||
@@ -702,25 +718,9 @@ ${(0, import_ascii.wrapInASCIIBox)(prettyMessage, 1)}`);
|
||||
"darwin": "/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary",
|
||||
"win32": `\\Google\\Chrome SxS\\Application\\chrome.exe`
|
||||
}));
|
||||
this._executables.push({
|
||||
type: "channel",
|
||||
name: "bidi-chromium",
|
||||
browserName: "chromium",
|
||||
directory: chromium.dir,
|
||||
executablePath: () => chromiumExecutable,
|
||||
executablePathOrDie: (sdkLanguage) => executablePathOrDie("chromium", chromiumExecutable, chromium.installByDefault, sdkLanguage),
|
||||
installType: "download-on-demand",
|
||||
_validateHostRequirements: (sdkLanguage) => this._validateHostRequirements(sdkLanguage, chromium.dir, ["chrome-linux"], [], ["chrome-win"]),
|
||||
downloadURLs: this._downloadURLs(chromium),
|
||||
browserVersion: chromium.browserVersion,
|
||||
_install: () => this._downloadExecutable(chromium, chromiumExecutable),
|
||||
_dependencyGroup: "chromium",
|
||||
_isHermeticInstallation: true
|
||||
});
|
||||
const firefox = descriptors.find((d) => d.name === "firefox");
|
||||
const firefoxExecutable = findExecutablePath(firefox.dir, "firefox");
|
||||
this._executables.push({
|
||||
type: "browser",
|
||||
name: "firefox",
|
||||
browserName: "firefox",
|
||||
directory: firefox.dir,
|
||||
@@ -729,15 +729,16 @@ ${(0, import_ascii.wrapInASCIIBox)(prettyMessage, 1)}`);
|
||||
installType: firefox.installByDefault ? "download-by-default" : "download-on-demand",
|
||||
_validateHostRequirements: (sdkLanguage) => this._validateHostRequirements(sdkLanguage, firefox.dir, ["firefox"], [], ["firefox"]),
|
||||
downloadURLs: this._downloadURLs(firefox),
|
||||
title: firefox.title,
|
||||
revision: firefox.revision,
|
||||
browserVersion: firefox.browserVersion,
|
||||
_install: () => this._downloadExecutable(firefox, firefoxExecutable),
|
||||
_install: (force) => this._downloadExecutable(firefox, force, firefoxExecutable),
|
||||
_dependencyGroup: "firefox",
|
||||
_isHermeticInstallation: true
|
||||
});
|
||||
const firefoxBeta = descriptors.find((d) => d.name === "firefox-beta");
|
||||
const firefoxBetaExecutable = findExecutablePath(firefoxBeta.dir, "firefox");
|
||||
this._executables.push({
|
||||
type: "tool",
|
||||
name: "firefox-beta",
|
||||
browserName: "firefox",
|
||||
directory: firefoxBeta.dir,
|
||||
@@ -746,8 +747,10 @@ ${(0, import_ascii.wrapInASCIIBox)(prettyMessage, 1)}`);
|
||||
installType: firefoxBeta.installByDefault ? "download-by-default" : "download-on-demand",
|
||||
_validateHostRequirements: (sdkLanguage) => this._validateHostRequirements(sdkLanguage, firefoxBeta.dir, ["firefox"], [], ["firefox"]),
|
||||
downloadURLs: this._downloadURLs(firefoxBeta),
|
||||
title: firefoxBeta.title,
|
||||
revision: firefoxBeta.revision,
|
||||
browserVersion: firefoxBeta.browserVersion,
|
||||
_install: () => this._downloadExecutable(firefoxBeta, firefoxBetaExecutable),
|
||||
_install: (force) => this._downloadExecutable(firefoxBeta, force, firefoxBetaExecutable),
|
||||
_dependencyGroup: "firefox",
|
||||
_isHermeticInstallation: true
|
||||
});
|
||||
@@ -764,7 +767,6 @@ ${(0, import_ascii.wrapInASCIIBox)(prettyMessage, 1)}`);
|
||||
import_path.default.join("minibrowser-wpe", "sys", "lib")
|
||||
];
|
||||
this._executables.push({
|
||||
type: "browser",
|
||||
name: "webkit",
|
||||
browserName: "webkit",
|
||||
directory: webkit.dir,
|
||||
@@ -773,19 +775,21 @@ ${(0, import_ascii.wrapInASCIIBox)(prettyMessage, 1)}`);
|
||||
installType: webkit.installByDefault ? "download-by-default" : "download-on-demand",
|
||||
_validateHostRequirements: (sdkLanguage) => this._validateHostRequirements(sdkLanguage, webkit.dir, webkitLinuxLddDirectories, ["libGLESv2.so.2", "libx264.so"], [""]),
|
||||
downloadURLs: this._downloadURLs(webkit),
|
||||
title: webkit.title,
|
||||
revision: webkit.revision,
|
||||
browserVersion: webkit.browserVersion,
|
||||
_install: () => this._downloadExecutable(webkit, webkitExecutable),
|
||||
_install: (force) => this._downloadExecutable(webkit, force, webkitExecutable),
|
||||
_dependencyGroup: "webkit",
|
||||
_isHermeticInstallation: true
|
||||
});
|
||||
this._executables.push({
|
||||
type: "channel",
|
||||
name: "webkit-wsl",
|
||||
browserName: "webkit",
|
||||
directory: webkit.dir,
|
||||
executablePath: () => webkitExecutable,
|
||||
executablePathOrDie: (sdkLanguage) => executablePathOrDie("webkit", webkitExecutable, webkit.installByDefault, sdkLanguage),
|
||||
installType: "download-on-demand",
|
||||
title: "Webkit in WSL",
|
||||
_validateHostRequirements: (sdkLanguage) => Promise.resolve(),
|
||||
_isHermeticInstallation: true,
|
||||
_install: async () => {
|
||||
@@ -807,7 +811,6 @@ ${(0, import_ascii.wrapInASCIIBox)(prettyMessage, 1)}`);
|
||||
const ffmpeg = descriptors.find((d) => d.name === "ffmpeg");
|
||||
const ffmpegExecutable = findExecutablePath(ffmpeg.dir, "ffmpeg");
|
||||
this._executables.push({
|
||||
type: "tool",
|
||||
name: "ffmpeg",
|
||||
browserName: void 0,
|
||||
directory: ffmpeg.dir,
|
||||
@@ -816,14 +819,15 @@ ${(0, import_ascii.wrapInASCIIBox)(prettyMessage, 1)}`);
|
||||
installType: ffmpeg.installByDefault ? "download-by-default" : "download-on-demand",
|
||||
_validateHostRequirements: () => Promise.resolve(),
|
||||
downloadURLs: this._downloadURLs(ffmpeg),
|
||||
_install: () => this._downloadExecutable(ffmpeg, ffmpegExecutable),
|
||||
title: ffmpeg.title,
|
||||
revision: ffmpeg.revision,
|
||||
_install: (force) => this._downloadExecutable(ffmpeg, force, ffmpegExecutable),
|
||||
_dependencyGroup: "tools",
|
||||
_isHermeticInstallation: true
|
||||
});
|
||||
const winldd = descriptors.find((d) => d.name === "winldd");
|
||||
const winlddExecutable = findExecutablePath(winldd.dir, "winldd");
|
||||
this._executables.push({
|
||||
type: "tool",
|
||||
name: "winldd",
|
||||
browserName: void 0,
|
||||
directory: winldd.dir,
|
||||
@@ -832,13 +836,14 @@ ${(0, import_ascii.wrapInASCIIBox)(prettyMessage, 1)}`);
|
||||
installType: process.platform === "win32" ? "download-by-default" : "none",
|
||||
_validateHostRequirements: () => Promise.resolve(),
|
||||
downloadURLs: this._downloadURLs(winldd),
|
||||
_install: () => this._downloadExecutable(winldd, winlddExecutable),
|
||||
title: winldd.title,
|
||||
revision: winldd.revision,
|
||||
_install: (force) => this._downloadExecutable(winldd, force, winlddExecutable),
|
||||
_dependencyGroup: "tools",
|
||||
_isHermeticInstallation: true
|
||||
});
|
||||
const android = descriptors.find((d) => d.name === "android");
|
||||
this._executables.push({
|
||||
type: "tool",
|
||||
name: "android",
|
||||
browserName: void 0,
|
||||
directory: android.dir,
|
||||
@@ -847,7 +852,9 @@ ${(0, import_ascii.wrapInASCIIBox)(prettyMessage, 1)}`);
|
||||
installType: "download-on-demand",
|
||||
_validateHostRequirements: () => Promise.resolve(),
|
||||
downloadURLs: this._downloadURLs(android),
|
||||
_install: () => this._downloadExecutable(android),
|
||||
title: android.title,
|
||||
revision: android.revision,
|
||||
_install: (force) => this._downloadExecutable(android, force),
|
||||
_dependencyGroup: "tools",
|
||||
_isHermeticInstallation: true
|
||||
});
|
||||
@@ -881,7 +888,6 @@ Run "${buildPlaywrightCLICommand(sdkLanguage, "install " + name)}"` : "";
|
||||
throw new Error(`Chromium distribution '${name}' is not found${location}${installation}`);
|
||||
};
|
||||
return {
|
||||
type: "channel",
|
||||
name,
|
||||
browserName: "chromium",
|
||||
directory: void 0,
|
||||
@@ -920,7 +926,6 @@ Run "${buildPlaywrightCLICommand(sdkLanguage, "install " + name)}"` : "";
|
||||
return void 0;
|
||||
};
|
||||
return {
|
||||
type: "channel",
|
||||
name,
|
||||
browserName: "firefox",
|
||||
directory: void 0,
|
||||
@@ -932,7 +937,7 @@ Run "${buildPlaywrightCLICommand(sdkLanguage, "install " + name)}"` : "";
|
||||
_install: install
|
||||
};
|
||||
}
|
||||
_createBidiChromiumChannel(name, lookAt, install) {
|
||||
_createBidiChromiumChannel(name, lookAt) {
|
||||
const executablePath = (sdkLanguage, shouldThrow) => {
|
||||
const suffix = lookAt[process.platform];
|
||||
if (!suffix) {
|
||||
@@ -956,21 +961,17 @@ Run "${buildPlaywrightCLICommand(sdkLanguage, "install " + name)}"` : "";
|
||||
if (!shouldThrow)
|
||||
return void 0;
|
||||
const location = prefixes.length ? ` at ${import_path.default.join(prefixes[0], suffix)}` : ``;
|
||||
const installation = install ? `
|
||||
Run "${buildPlaywrightCLICommand(sdkLanguage, "install " + name)}"` : "";
|
||||
throw new Error(`Chromium distribution '${name}' is not found${location}${installation}`);
|
||||
throw new Error(`Chromium distribution '${name}' is not found${location}`);
|
||||
};
|
||||
return {
|
||||
type: "channel",
|
||||
name,
|
||||
browserName: "chromium",
|
||||
directory: void 0,
|
||||
executablePath: (sdkLanguage) => executablePath(sdkLanguage, false),
|
||||
executablePathOrDie: (sdkLanguage) => executablePath(sdkLanguage, true),
|
||||
installType: install ? "install-script" : "none",
|
||||
installType: "none",
|
||||
_validateHostRequirements: () => Promise.resolve(),
|
||||
_isHermeticInstallation: false,
|
||||
_install: install
|
||||
_isHermeticInstallation: false
|
||||
};
|
||||
}
|
||||
executables() {
|
||||
@@ -1051,7 +1052,7 @@ Run "${buildPlaywrightCLICommand(sdkLanguage, "install " + name)}"` : "";
|
||||
].join("\n"), 1) + "\n\n");
|
||||
return;
|
||||
}
|
||||
await executable._install();
|
||||
await executable._install(!!options?.force);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.code === "ELOCKED") {
|
||||
@@ -1123,8 +1124,16 @@ Run "${buildPlaywrightCLICommand(sdkLanguage, "install " + name)}"` : "";
|
||||
const downloadPathTemplate = paths[import_hostPlatform.hostPlatform] || paths["<unknown>"];
|
||||
if (!downloadPathTemplate)
|
||||
return [];
|
||||
const downloadPath = util.format(downloadPathTemplate, descriptor.revision);
|
||||
let downloadURLs = PLAYWRIGHT_CDN_MIRRORS.map((mirror) => `${mirror}/${downloadPath}`);
|
||||
let downloadPath;
|
||||
let mirrors;
|
||||
if (typeof downloadPathTemplate === "function") {
|
||||
const result = downloadPathTemplate(descriptor);
|
||||
downloadPath = result.path;
|
||||
mirrors = result.mirrors;
|
||||
} else {
|
||||
downloadPath = util.format(downloadPathTemplate, descriptor.revision);
|
||||
mirrors = PLAYWRIGHT_CDN_MIRRORS;
|
||||
}
|
||||
let downloadHostEnv;
|
||||
if (descriptor.name.startsWith("chromium"))
|
||||
downloadHostEnv = "PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST";
|
||||
@@ -1134,10 +1143,10 @@ Run "${buildPlaywrightCLICommand(sdkLanguage, "install " + name)}"` : "";
|
||||
downloadHostEnv = "PLAYWRIGHT_WEBKIT_DOWNLOAD_HOST";
|
||||
const customHostOverride = downloadHostEnv && (0, import_utils.getFromENV)(downloadHostEnv) || (0, import_utils.getFromENV)("PLAYWRIGHT_DOWNLOAD_HOST");
|
||||
if (customHostOverride)
|
||||
downloadURLs = [`${customHostOverride}/${downloadPath}`];
|
||||
return downloadURLs;
|
||||
mirrors = [customHostOverride];
|
||||
return mirrors.map((mirror) => `${mirror}/${downloadPath}`);
|
||||
}
|
||||
async _downloadExecutable(descriptor, executablePath) {
|
||||
async _downloadExecutable(descriptor, force, executablePath) {
|
||||
const downloadURLs = this._downloadURLs(descriptor);
|
||||
if (!downloadURLs.length)
|
||||
throw new Error(`ERROR: Playwright does not support ${descriptor.name} on ${import_hostPlatform.hostPlatform}`);
|
||||
@@ -1150,18 +1159,22 @@ Run "${buildPlaywrightCLICommand(sdkLanguage, "install " + name)}"` : "";
|
||||
else
|
||||
(0, import_browserFetcher.logPolitely)(message);
|
||||
}
|
||||
const displayName = descriptor.name.split("-").map((word) => {
|
||||
return word === "ffmpeg" ? "FFMPEG" : word.charAt(0).toUpperCase() + word.slice(1);
|
||||
}).join(" ");
|
||||
const title = descriptor.browserVersion ? `${displayName} ${descriptor.browserVersion} (playwright build v${descriptor.revision})` : `${displayName} playwright build v${descriptor.revision}`;
|
||||
const title = this.calculateDownloadTitle(descriptor);
|
||||
const downloadFileName = `playwright-download-${descriptor.name}-${import_hostPlatform.hostPlatform}-${descriptor.revision}.zip`;
|
||||
const downloadSocketTimeoutEnv = (0, import_utils.getFromENV)("PLAYWRIGHT_DOWNLOAD_CONNECTION_TIMEOUT");
|
||||
const downloadSocketTimeout = +(downloadSocketTimeoutEnv || "0") || import_network.NET_DEFAULT_TIMEOUT;
|
||||
await (0, import_browserFetcher.downloadBrowserWithProgressBar)(title, descriptor.dir, executablePath, downloadURLs, downloadFileName, downloadSocketTimeout).catch((e) => {
|
||||
await (0, import_browserFetcher.downloadBrowserWithProgressBar)(title, descriptor.dir, executablePath, downloadURLs, downloadFileName, downloadSocketTimeout, force).catch((e) => {
|
||||
throw new Error(`Failed to download ${title}, caused by
|
||||
${e.stack}`);
|
||||
});
|
||||
}
|
||||
calculateDownloadTitle(descriptor) {
|
||||
const title = descriptor.title ?? descriptor.name.split("-").map((word) => {
|
||||
return word === "ffmpeg" ? "FFmpeg" : word.charAt(0).toUpperCase() + word.slice(1);
|
||||
}).join(" ");
|
||||
const version = descriptor.browserVersion ? " " + descriptor.browserVersion : "";
|
||||
return `${title}${version} (playwright ${descriptor.name} v${descriptor.revision})`;
|
||||
}
|
||||
async _installMSEdgeChannel(channel, scripts) {
|
||||
const scriptArgs = [];
|
||||
if (process.platform !== "linux") {
|
||||
@@ -1234,7 +1247,7 @@ ${e.stack}`);
|
||||
linkTarget = (await import_fs.default.promises.readFile(linkPath)).toString();
|
||||
const browsersJSON = require(import_path.default.join(linkTarget, "browsers.json"));
|
||||
const descriptors = readDescriptors(browsersJSON);
|
||||
for (const browserName of allDownloadable) {
|
||||
for (const browserName of allDownloadableDirectoriesThatEverExisted) {
|
||||
const descriptor = descriptors.find((d) => d.name === browserName);
|
||||
if (!descriptor)
|
||||
continue;
|
||||
@@ -1279,13 +1292,18 @@ ${e.stack}`);
|
||||
_defaultBrowsersToInstall(options) {
|
||||
let executables = this.defaultExecutables();
|
||||
if (options.shell === "no")
|
||||
executables = executables.filter((e) => e.name !== "chromium-headless-shell");
|
||||
executables = executables.filter((e) => e.name !== "chromium-headless-shell" && e.name !== "chromium-tip-of-tree-headless-shell");
|
||||
if (options.shell === "only")
|
||||
executables = executables.filter((e) => e.name !== "chromium");
|
||||
executables = executables.filter((e) => e.name !== "chromium" && e.name !== "chromium-tip-of-tree");
|
||||
return executables;
|
||||
}
|
||||
suggestedBrowsersToInstall() {
|
||||
return this.executables().filter((e) => e.installType !== "none" && e.type !== "tool").map((e) => e.name).join(", ");
|
||||
const names = this.executables().filter((e) => e.installType !== "none").map((e) => e.name);
|
||||
names.push(...chromiumAliases);
|
||||
return names.sort().join(", ");
|
||||
}
|
||||
isChromiumAlias(name) {
|
||||
return chromiumAliases.includes(name);
|
||||
}
|
||||
resolveBrowsers(aliases, options) {
|
||||
if (aliases.length === 0)
|
||||
@@ -1298,15 +1316,20 @@ ${e.stack}`);
|
||||
faultyArguments.push(arg);
|
||||
else
|
||||
executables.push(executable);
|
||||
if (executable?.browserName === "chromium")
|
||||
if (executable?.browserName)
|
||||
executables.push(this.findExecutable("ffmpeg"));
|
||||
};
|
||||
for (const alias of aliases) {
|
||||
if (alias === "chromium") {
|
||||
if (alias === "chromium" || chromiumAliases.includes(alias)) {
|
||||
if (options.shell !== "only")
|
||||
handleArgument("chromium");
|
||||
if (options.shell !== "no")
|
||||
handleArgument("chromium-headless-shell");
|
||||
} else if (alias === "chromium-tip-of-tree") {
|
||||
if (options.shell !== "only")
|
||||
handleArgument("chromium-tip-of-tree");
|
||||
if (options.shell !== "no")
|
||||
handleArgument("chromium-tip-of-tree-headless-shell");
|
||||
} else {
|
||||
handleArgument(alias);
|
||||
}
|
||||
|
||||
3
node_modules/playwright-core/lib/server/registry/oopDownloadBrowserMain.js
generated
vendored
3
node_modules/playwright-core/lib/server/registry/oopDownloadBrowserMain.js
generated
vendored
@@ -29,6 +29,7 @@ var import_path = __toESM(require("path"));
|
||||
var import_manualPromise = require("../../utils/isomorphic/manualPromise");
|
||||
var import_network = require("../utils/network");
|
||||
var import_zipBundle = require("../../zipBundle");
|
||||
var import_fileUtils = require("../utils/fileUtils");
|
||||
function log(message) {
|
||||
process.send?.({ method: "log", params: { message } });
|
||||
}
|
||||
@@ -99,6 +100,8 @@ function downloadFile(options) {
|
||||
async function main(options) {
|
||||
await downloadFile(options);
|
||||
log(`SUCCESS downloading ${options.title}`);
|
||||
log(`removing existing browser directory if any`);
|
||||
await (0, import_fileUtils.removeFolders)([options.browserDirectory]);
|
||||
log(`extracting archive`);
|
||||
await (0, import_zipBundle.extract)(options.zipPath, { dir: options.browserDirectory });
|
||||
if (options.executablePath) {
|
||||
|
||||
190
node_modules/playwright-core/lib/server/screencast.js
generated
vendored
Normal file
190
node_modules/playwright-core/lib/server/screencast.js
generated
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
"use strict";
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||
// If the importer is in node compatibility mode or this is not an ESM
|
||||
// file that has been converted to a CommonJS file using a Babel-
|
||||
// compatible transform (i.e. "__esModule" has not been set), then set
|
||||
// "default" to the CommonJS "module.exports" for node compatibility.
|
||||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||
mod
|
||||
));
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var screencast_exports = {};
|
||||
__export(screencast_exports, {
|
||||
Screencast: () => Screencast
|
||||
});
|
||||
module.exports = __toCommonJS(screencast_exports);
|
||||
var import_path = __toESM(require("path"));
|
||||
var import_utils = require("../utils");
|
||||
var import_utils2 = require("../utils");
|
||||
var import_videoRecorder = require("./videoRecorder");
|
||||
var import_page = require("./page");
|
||||
var import_registry = require("./registry");
|
||||
class Screencast {
|
||||
constructor(page) {
|
||||
this._videoRecorder = null;
|
||||
this._videoId = null;
|
||||
this._screencastClients = /* @__PURE__ */ new Set();
|
||||
// Aiming at 25 fps by default - each frame is 40ms, but we give some slack with 35ms.
|
||||
// When throttling for tracing, 200ms between frames, except for 10 frames around the action.
|
||||
this._frameThrottler = new FrameThrottler(10, 35, 200);
|
||||
this._frameListener = null;
|
||||
this._page = page;
|
||||
}
|
||||
stopFrameThrottler() {
|
||||
this._frameThrottler.dispose();
|
||||
}
|
||||
setOptions(options) {
|
||||
this._setOptions(options).catch((e) => import_utils2.debugLogger.log("error", e));
|
||||
this._frameThrottler.setThrottlingEnabled(!!options);
|
||||
}
|
||||
throttleFrameAck(ack) {
|
||||
this._frameThrottler.ack(ack);
|
||||
}
|
||||
temporarilyDisableThrottling() {
|
||||
this._frameThrottler.recharge();
|
||||
}
|
||||
launchVideoRecorder() {
|
||||
const recordVideo = this._page.browserContext._options.recordVideo;
|
||||
if (!recordVideo)
|
||||
return void 0;
|
||||
(0, import_utils.assert)(!this._videoId);
|
||||
this._videoId = (0, import_utils.createGuid)();
|
||||
const outputFile = import_path.default.join(recordVideo.dir, this._videoId + ".webm");
|
||||
const videoOptions = {
|
||||
// validateBrowserContextOptions ensures correct video size.
|
||||
...recordVideo.size,
|
||||
outputFile
|
||||
};
|
||||
const ffmpegPath = import_registry.registry.findExecutable("ffmpeg").executablePathOrDie(this._page.browserContext._browser.sdkLanguage());
|
||||
this._videoRecorder = new import_videoRecorder.VideoRecorder(ffmpegPath, videoOptions);
|
||||
this._frameListener = import_utils.eventsHelper.addEventListener(this._page, import_page.Page.Events.ScreencastFrame, (frame) => this._videoRecorder.writeFrame(frame.buffer, frame.frameSwapWallTime / 1e3));
|
||||
this._page.waitForInitializedOrError().then((p) => {
|
||||
if (p instanceof Error)
|
||||
this.stopVideoRecording().catch(() => {
|
||||
});
|
||||
});
|
||||
return videoOptions;
|
||||
}
|
||||
async startVideoRecording(options) {
|
||||
const videoId = this._videoId;
|
||||
(0, import_utils.assert)(videoId);
|
||||
this._page.once(import_page.Page.Events.Close, () => this.stopVideoRecording().catch(() => {
|
||||
}));
|
||||
const gotFirstFrame = new Promise((f) => this._page.once(import_page.Page.Events.ScreencastFrame, f));
|
||||
await this._startScreencast(this._videoRecorder, {
|
||||
quality: 90,
|
||||
width: options.width,
|
||||
height: options.height
|
||||
});
|
||||
gotFirstFrame.then(() => {
|
||||
this._page.browserContext._browser._videoStarted(this._page.browserContext, videoId, options.outputFile, this._page.waitForInitializedOrError());
|
||||
});
|
||||
}
|
||||
async stopVideoRecording() {
|
||||
if (!this._videoId)
|
||||
return;
|
||||
if (this._frameListener)
|
||||
import_utils.eventsHelper.removeEventListeners([this._frameListener]);
|
||||
this._frameListener = null;
|
||||
const videoId = this._videoId;
|
||||
this._videoId = null;
|
||||
const videoRecorder = this._videoRecorder;
|
||||
this._videoRecorder = null;
|
||||
await this._stopScreencast(videoRecorder);
|
||||
await videoRecorder.stop();
|
||||
const video = this._page.browserContext._browser._takeVideo(videoId);
|
||||
video?.reportFinished();
|
||||
}
|
||||
async _setOptions(options) {
|
||||
if (options)
|
||||
await this._startScreencast(this, options);
|
||||
else
|
||||
await this._stopScreencast(this);
|
||||
}
|
||||
async _startScreencast(client, options) {
|
||||
this._screencastClients.add(client);
|
||||
if (this._screencastClients.size === 1) {
|
||||
await this._page.delegate.startScreencast({
|
||||
width: options.width,
|
||||
height: options.height,
|
||||
quality: options.quality
|
||||
});
|
||||
}
|
||||
}
|
||||
async _stopScreencast(client) {
|
||||
this._screencastClients.delete(client);
|
||||
if (!this._screencastClients.size)
|
||||
await this._page.delegate.stopScreencast();
|
||||
}
|
||||
}
|
||||
class FrameThrottler {
|
||||
constructor(nonThrottledFrames, defaultInterval, throttlingInterval) {
|
||||
this._acks = [];
|
||||
this._throttlingEnabled = false;
|
||||
this._nonThrottledFrames = nonThrottledFrames;
|
||||
this._budget = nonThrottledFrames;
|
||||
this._defaultInterval = defaultInterval;
|
||||
this._throttlingInterval = throttlingInterval;
|
||||
this._tick();
|
||||
}
|
||||
dispose() {
|
||||
if (this._timeoutId) {
|
||||
clearTimeout(this._timeoutId);
|
||||
this._timeoutId = void 0;
|
||||
}
|
||||
}
|
||||
setThrottlingEnabled(enabled) {
|
||||
this._throttlingEnabled = enabled;
|
||||
}
|
||||
recharge() {
|
||||
for (const ack of this._acks)
|
||||
ack();
|
||||
this._acks = [];
|
||||
this._budget = this._nonThrottledFrames;
|
||||
if (this._timeoutId) {
|
||||
clearTimeout(this._timeoutId);
|
||||
this._tick();
|
||||
}
|
||||
}
|
||||
ack(ack) {
|
||||
if (!this._timeoutId) {
|
||||
ack();
|
||||
return;
|
||||
}
|
||||
this._acks.push(ack);
|
||||
}
|
||||
_tick() {
|
||||
const ack = this._acks.shift();
|
||||
if (ack) {
|
||||
--this._budget;
|
||||
ack();
|
||||
}
|
||||
if (this._throttlingEnabled && this._budget <= 0) {
|
||||
this._timeoutId = setTimeout(() => this._tick(), this._throttlingInterval);
|
||||
} else {
|
||||
this._timeoutId = setTimeout(() => this._tick(), this._defaultInterval);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
Screencast
|
||||
});
|
||||
22
node_modules/playwright-core/lib/server/trace/recorder/snapshotterInjected.js
generated
vendored
22
node_modules/playwright-core/lib/server/trace/recorder/snapshotterInjected.js
generated
vendored
@@ -61,6 +61,7 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
|
||||
constructor() {
|
||||
this._lastSnapshotNumber = 0;
|
||||
this._staleStyleSheets = /* @__PURE__ */ new Set();
|
||||
this._modifiedStyleSheets = /* @__PURE__ */ new Set();
|
||||
this._readingStyleSheet = false;
|
||||
const invalidateCSSGroupingRule = (rule) => {
|
||||
if (rule.parentStyleSheet)
|
||||
@@ -76,6 +77,10 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
|
||||
this._interceptNativeMethod(window.CSSGroupingRule.prototype, "insertRule", invalidateCSSGroupingRule);
|
||||
this._interceptNativeMethod(window.CSSGroupingRule.prototype, "deleteRule", invalidateCSSGroupingRule);
|
||||
this._interceptNativeGetter(window.CSSGroupingRule.prototype, "cssRules", invalidateCSSGroupingRule);
|
||||
this._interceptNativeSetter(window.StyleSheet.prototype, "disabled", (sheet) => {
|
||||
if (sheet instanceof CSSStyleSheet)
|
||||
this._invalidateStyleSheet(sheet);
|
||||
});
|
||||
this._interceptNativeAsyncMethod(window.CSSStyleSheet.prototype, "replace", (sheet) => this._invalidateStyleSheet(sheet));
|
||||
this._fakeBase = document.createElement("base");
|
||||
this._observer = new MutationObserver((list) => this._handleMutations(list));
|
||||
@@ -148,6 +153,17 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
|
||||
}
|
||||
});
|
||||
}
|
||||
_interceptNativeSetter(obj, prop, cb) {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
|
||||
Object.defineProperty(obj, prop, {
|
||||
...descriptor,
|
||||
set: function(value) {
|
||||
const result = descriptor.set.call(this, value);
|
||||
cb(this, value);
|
||||
return result;
|
||||
}
|
||||
});
|
||||
}
|
||||
_handleMutations(list) {
|
||||
for (const mutation of list)
|
||||
ensureCachedData(mutation.target).attributesCached = void 0;
|
||||
@@ -156,6 +172,8 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
|
||||
if (this._readingStyleSheet)
|
||||
return;
|
||||
this._staleStyleSheets.add(sheet);
|
||||
if (sheet.href !== null)
|
||||
this._modifiedStyleSheets.add(sheet);
|
||||
}
|
||||
_updateStyleElementStyleSheetTextIfNeeded(sheet, forceText) {
|
||||
const data = ensureCachedData(sheet);
|
||||
@@ -248,6 +266,8 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
|
||||
_getSheetText(sheet) {
|
||||
this._readingStyleSheet = true;
|
||||
try {
|
||||
if (sheet.disabled)
|
||||
return "";
|
||||
const rules = [];
|
||||
for (const rule of sheet.cssRules)
|
||||
rules.push(rule.cssText);
|
||||
@@ -518,7 +538,7 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
|
||||
wallTime: Date.now(),
|
||||
collectionTime: 0
|
||||
};
|
||||
for (const sheet of this._staleStyleSheets) {
|
||||
for (const sheet of this._modifiedStyleSheets) {
|
||||
if (sheet.href === null)
|
||||
continue;
|
||||
const content = this._updateLinkStyleSheetTextIfNeeded(sheet, snapshotNumber);
|
||||
|
||||
42
node_modules/playwright-core/lib/server/trace/recorder/tracing.js
generated
vendored
42
node_modules/playwright-core/lib/server/trace/recorder/tracing.js
generated
vendored
@@ -222,7 +222,7 @@ class Tracing extends import_instrumentation.SdkObject {
|
||||
if (!(this._context instanceof import_browserContext.BrowserContext))
|
||||
return;
|
||||
for (const page of this._context.pages())
|
||||
page.setScreencastOptions(null);
|
||||
page.screencast.setOptions(null);
|
||||
}
|
||||
_allocateNewTraceFile(state) {
|
||||
const suffix = state.chunkOrdinal ? `-chunk${state.chunkOrdinal}` : ``;
|
||||
@@ -326,23 +326,21 @@ class Tracing extends import_instrumentation.SdkObject {
|
||||
return { artifact };
|
||||
}
|
||||
async _captureSnapshot(snapshotName, sdkObject, metadata) {
|
||||
if (!this._snapshotter)
|
||||
if (!snapshotName || !sdkObject.attribution.page)
|
||||
return;
|
||||
if (!sdkObject.attribution.page)
|
||||
return;
|
||||
if (!this._snapshotter.started())
|
||||
return;
|
||||
if (!shouldCaptureSnapshot(metadata))
|
||||
return;
|
||||
await this._snapshotter.captureSnapshot(sdkObject.attribution.page, metadata.id, snapshotName).catch(() => {
|
||||
await this._snapshotter?.captureSnapshot(sdkObject.attribution.page, metadata.id, snapshotName).catch(() => {
|
||||
});
|
||||
}
|
||||
onBeforeCall(sdkObject, metadata) {
|
||||
const event = createBeforeActionTraceEvent(metadata, this._currentGroupId());
|
||||
_shouldCaptureSnapshot(sdkObject, metadata) {
|
||||
return !!this._snapshotter?.started() && shouldCaptureSnapshot(metadata) && !!sdkObject.attribution.page;
|
||||
}
|
||||
onBeforeCall(sdkObject, metadata, parentId) {
|
||||
const event = createBeforeActionTraceEvent(metadata, parentId ?? this._currentGroupId());
|
||||
if (!event)
|
||||
return Promise.resolve();
|
||||
sdkObject.attribution.page?.temporarilyDisableTracingScreencastThrottling();
|
||||
event.beforeSnapshot = `before@${metadata.id}`;
|
||||
sdkObject.attribution.page?.screencast.temporarilyDisableThrottling();
|
||||
if (this._shouldCaptureSnapshot(sdkObject, metadata))
|
||||
event.beforeSnapshot = `before@${metadata.id}`;
|
||||
this._state?.callIds.add(metadata.id);
|
||||
this._appendTraceEvent(event);
|
||||
return this._captureSnapshot(event.beforeSnapshot, sdkObject, metadata);
|
||||
@@ -353,8 +351,9 @@ class Tracing extends import_instrumentation.SdkObject {
|
||||
const event = createInputActionTraceEvent(metadata);
|
||||
if (!event)
|
||||
return Promise.resolve();
|
||||
sdkObject.attribution.page?.temporarilyDisableTracingScreencastThrottling();
|
||||
event.inputSnapshot = `input@${metadata.id}`;
|
||||
sdkObject.attribution.page?.screencast.temporarilyDisableThrottling();
|
||||
if (this._shouldCaptureSnapshot(sdkObject, metadata))
|
||||
event.inputSnapshot = `input@${metadata.id}`;
|
||||
this._appendTraceEvent(event);
|
||||
return this._captureSnapshot(event.inputSnapshot, sdkObject, metadata);
|
||||
}
|
||||
@@ -369,15 +368,16 @@ class Tracing extends import_instrumentation.SdkObject {
|
||||
if (event)
|
||||
this._appendTraceEvent(event);
|
||||
}
|
||||
async onAfterCall(sdkObject, metadata) {
|
||||
onAfterCall(sdkObject, metadata) {
|
||||
if (!this._state?.callIds.has(metadata.id))
|
||||
return;
|
||||
return Promise.resolve();
|
||||
this._state?.callIds.delete(metadata.id);
|
||||
const event = createAfterActionTraceEvent(metadata);
|
||||
if (!event)
|
||||
return;
|
||||
sdkObject.attribution.page?.temporarilyDisableTracingScreencastThrottling();
|
||||
event.afterSnapshot = `after@${metadata.id}`;
|
||||
return Promise.resolve();
|
||||
sdkObject.attribution.page?.screencast.temporarilyDisableThrottling();
|
||||
if (this._shouldCaptureSnapshot(sdkObject, metadata))
|
||||
event.afterSnapshot = `after@${metadata.id}`;
|
||||
this._appendTraceEvent(event);
|
||||
return this._captureSnapshot(event.afterSnapshot, sdkObject, metadata);
|
||||
}
|
||||
@@ -484,7 +484,7 @@ class Tracing extends import_instrumentation.SdkObject {
|
||||
this._appendTraceEvent(event);
|
||||
}
|
||||
_startScreencastInPage(page) {
|
||||
page.setScreencastOptions(kScreencastOptions);
|
||||
page.screencast.setOptions(kScreencastOptions);
|
||||
const prefix = page.guid;
|
||||
this._screencastListeners.push(
|
||||
import_eventsHelper.eventsHelper.addEventListener(page, import_page.Page.Events.ScreencastFrame, (params) => {
|
||||
|
||||
87
node_modules/playwright-core/lib/server/trace/test/inMemorySnapshotter.js
generated
vendored
87
node_modules/playwright-core/lib/server/trace/test/inMemorySnapshotter.js
generated
vendored
@@ -1,87 +0,0 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var inMemorySnapshotter_exports = {};
|
||||
__export(inMemorySnapshotter_exports, {
|
||||
InMemorySnapshotter: () => InMemorySnapshotter
|
||||
});
|
||||
module.exports = __toCommonJS(inMemorySnapshotter_exports);
|
||||
var import_snapshotStorage = require("../../../../../trace-viewer/src/sw/snapshotStorage");
|
||||
var import_utils = require("../../../utils");
|
||||
var import_harTracer = require("../../har/harTracer");
|
||||
var import_snapshotter = require("../recorder/snapshotter");
|
||||
class InMemorySnapshotter {
|
||||
constructor(context) {
|
||||
this._blobs = /* @__PURE__ */ new Map();
|
||||
this._snapshotReadyPromises = /* @__PURE__ */ new Map();
|
||||
this._snapshotCount = 0;
|
||||
this._snapshotter = new import_snapshotter.Snapshotter(context, this);
|
||||
this._harTracer = new import_harTracer.HarTracer(context, null, this, { content: "attach", includeTraceInfo: true, recordRequestOverrides: false, waitForContentOnStop: false });
|
||||
this._storage = new import_snapshotStorage.SnapshotStorage();
|
||||
}
|
||||
async initialize() {
|
||||
await this._snapshotter.start();
|
||||
this._harTracer.start({ omitScripts: true });
|
||||
}
|
||||
async reset() {
|
||||
await this._snapshotter.reset();
|
||||
await this._harTracer.flush();
|
||||
this._harTracer.stop();
|
||||
this._harTracer.start({ omitScripts: true });
|
||||
}
|
||||
async dispose() {
|
||||
this._snapshotter.dispose();
|
||||
await this._harTracer.flush();
|
||||
this._harTracer.stop();
|
||||
}
|
||||
async captureSnapshot(page, callId, snapshotName) {
|
||||
if (this._snapshotReadyPromises.has(snapshotName))
|
||||
throw new Error("Duplicate snapshot name: " + snapshotName);
|
||||
this._snapshotter.captureSnapshot(page, callId, snapshotName).catch(() => {
|
||||
});
|
||||
const promise = new import_utils.ManualPromise();
|
||||
this._snapshotReadyPromises.set(snapshotName, promise);
|
||||
return promise;
|
||||
}
|
||||
onEntryStarted(entry) {
|
||||
}
|
||||
onEntryFinished(entry) {
|
||||
this._storage.addResource("", entry);
|
||||
}
|
||||
onContentBlob(sha1, buffer) {
|
||||
this._blobs.set(sha1, buffer);
|
||||
}
|
||||
onSnapshotterBlob(blob) {
|
||||
this._blobs.set(blob.sha1, blob.buffer);
|
||||
}
|
||||
onFrameSnapshot(snapshot) {
|
||||
++this._snapshotCount;
|
||||
const renderer = this._storage.addFrameSnapshot("", snapshot, []);
|
||||
this._snapshotReadyPromises.get(snapshot.snapshotName || "")?.resolve(renderer);
|
||||
}
|
||||
async resourceContentForTest(sha1) {
|
||||
return this._blobs.get(sha1);
|
||||
}
|
||||
snapshotCount() {
|
||||
return this._snapshotCount;
|
||||
}
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
InMemorySnapshotter
|
||||
});
|
||||
72
node_modules/playwright-core/lib/server/trace/viewer/traceParser.js
generated
vendored
Normal file
72
node_modules/playwright-core/lib/server/trace/viewer/traceParser.js
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
"use strict";
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||
// If the importer is in node compatibility mode or this is not an ESM
|
||||
// file that has been converted to a CommonJS file using a Babel-
|
||||
// compatible transform (i.e. "__esModule" has not been set), then set
|
||||
// "default" to the CommonJS "module.exports" for node compatibility.
|
||||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||
mod
|
||||
));
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var traceParser_exports = {};
|
||||
__export(traceParser_exports, {
|
||||
ZipTraceLoaderBackend: () => ZipTraceLoaderBackend
|
||||
});
|
||||
module.exports = __toCommonJS(traceParser_exports);
|
||||
var import_url = __toESM(require("url"));
|
||||
var import_zipFile = require("../../utils/zipFile");
|
||||
class ZipTraceLoaderBackend {
|
||||
constructor(traceFile) {
|
||||
this._traceFile = traceFile;
|
||||
this._zipFile = new import_zipFile.ZipFile(traceFile);
|
||||
}
|
||||
isLive() {
|
||||
return false;
|
||||
}
|
||||
traceURL() {
|
||||
return import_url.default.pathToFileURL(this._traceFile).toString();
|
||||
}
|
||||
async entryNames() {
|
||||
return await this._zipFile.entries();
|
||||
}
|
||||
async hasEntry(entryName) {
|
||||
const entries = await this.entryNames();
|
||||
return entries.includes(entryName);
|
||||
}
|
||||
async readText(entryName) {
|
||||
try {
|
||||
const buffer = await this._zipFile.read(entryName);
|
||||
return buffer.toString("utf-8");
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
async readBlob(entryName) {
|
||||
try {
|
||||
const buffer = await this._zipFile.read(entryName);
|
||||
return new Blob([new Uint8Array(buffer)]);
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
ZipTraceLoaderBackend
|
||||
});
|
||||
38
node_modules/playwright-core/lib/server/trace/viewer/traceViewer.js
generated
vendored
38
node_modules/playwright-core/lib/server/trace/viewer/traceViewer.js
generated
vendored
@@ -47,20 +47,21 @@ var import_launchApp2 = require("../../launchApp");
|
||||
var import_playwright = require("../../playwright");
|
||||
var import_progress = require("../../progress");
|
||||
const tracesDirMarker = "traces.dir";
|
||||
function validateTraceUrl(traceUrl) {
|
||||
if (!traceUrl)
|
||||
return traceUrl;
|
||||
if (traceUrl.startsWith("http://") || traceUrl.startsWith("https://"))
|
||||
return traceUrl;
|
||||
if (traceUrl.endsWith(".json"))
|
||||
return traceUrl;
|
||||
function validateTraceUrlOrPath(traceFileOrUrl) {
|
||||
if (!traceFileOrUrl)
|
||||
return traceFileOrUrl;
|
||||
if (traceFileOrUrl.startsWith("http://") || traceFileOrUrl.startsWith("https://"))
|
||||
return traceFileOrUrl;
|
||||
let traceFile = traceFileOrUrl;
|
||||
if (traceFile.endsWith(".json"))
|
||||
return toFilePathUrl(traceFile);
|
||||
try {
|
||||
const stat = import_fs.default.statSync(traceUrl);
|
||||
const stat = import_fs.default.statSync(traceFile);
|
||||
if (stat.isDirectory())
|
||||
return import_path.default.join(traceUrl, tracesDirMarker);
|
||||
return traceUrl;
|
||||
traceFile = import_path.default.join(traceFile, tracesDirMarker);
|
||||
return toFilePathUrl(traceFile);
|
||||
} catch {
|
||||
throw new Error(`Trace file ${traceUrl} does not exist!`);
|
||||
throw new Error(`Trace file ${traceFileOrUrl} does not exist!`);
|
||||
}
|
||||
}
|
||||
async function startTraceViewerServer(options) {
|
||||
@@ -126,7 +127,7 @@ async function installRootRedirect(server, traceUrl, options) {
|
||||
});
|
||||
}
|
||||
async function runTraceViewerApp(traceUrl, browserName, options, exitOnClose) {
|
||||
traceUrl = validateTraceUrl(traceUrl);
|
||||
traceUrl = validateTraceUrlOrPath(traceUrl);
|
||||
const server = await startTraceViewerServer(options);
|
||||
await installRootRedirect(server, traceUrl, options);
|
||||
const page = await openTraceViewerApp(server.urlPrefix("precise"), browserName, options);
|
||||
@@ -135,7 +136,7 @@ async function runTraceViewerApp(traceUrl, browserName, options, exitOnClose) {
|
||||
return page;
|
||||
}
|
||||
async function runTraceInBrowser(traceUrl, options) {
|
||||
traceUrl = validateTraceUrl(traceUrl);
|
||||
traceUrl = validateTraceUrlOrPath(traceUrl);
|
||||
const server = await startTraceViewerServer(options);
|
||||
await installRootRedirect(server, traceUrl, options);
|
||||
await openTraceInBrowser(server.urlPrefix("human-readable"));
|
||||
@@ -177,8 +178,8 @@ async function openTraceInBrowser(url) {
|
||||
class StdinServer {
|
||||
constructor() {
|
||||
process.stdin.on("data", (data) => {
|
||||
const url = data.toString().trim();
|
||||
if (url === this._traceUrl)
|
||||
const url = validateTraceUrlOrPath(data.toString().trim());
|
||||
if (!url || url === this._traceUrl)
|
||||
return;
|
||||
if (url.endsWith(".json"))
|
||||
this._pollLoadTrace(url);
|
||||
@@ -221,15 +222,18 @@ function traceDescriptor(traceDir, tracePrefix) {
|
||||
};
|
||||
for (const name of import_fs.default.readdirSync(traceDir)) {
|
||||
if (!tracePrefix || name.startsWith(tracePrefix))
|
||||
result.entries.push({ name, path: import_path.default.join(traceDir, name) });
|
||||
result.entries.push({ name, path: toFilePathUrl(import_path.default.join(traceDir, name)) });
|
||||
}
|
||||
const resourcesDir = import_path.default.join(traceDir, "resources");
|
||||
if (import_fs.default.existsSync(resourcesDir)) {
|
||||
for (const name of import_fs.default.readdirSync(resourcesDir))
|
||||
result.entries.push({ name: "resources/" + name, path: import_path.default.join(resourcesDir, name) });
|
||||
result.entries.push({ name: "resources/" + name, path: toFilePathUrl(import_path.default.join(resourcesDir, name)) });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function toFilePathUrl(filePath) {
|
||||
return `file?path=${encodeURIComponent(filePath)}`;
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
installRootRedirect,
|
||||
|
||||
89
node_modules/playwright-core/lib/server/utils/expectUtils.js
generated
vendored
89
node_modules/playwright-core/lib/server/utils/expectUtils.js
generated
vendored
@@ -18,10 +18,16 @@ var __copyProps = (to, from, except, desc) => {
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var expectUtils_exports = {};
|
||||
__export(expectUtils_exports, {
|
||||
serializeExpectedTextValues: () => serializeExpectedTextValues
|
||||
callLogText: () => callLogText,
|
||||
formatMatcherMessage: () => formatMatcherMessage,
|
||||
printReceivedStringContainExpectedResult: () => printReceivedStringContainExpectedResult,
|
||||
printReceivedStringContainExpectedSubstring: () => printReceivedStringContainExpectedSubstring,
|
||||
serializeExpectedTextValues: () => serializeExpectedTextValues,
|
||||
simpleMatcherUtils: () => simpleMatcherUtils
|
||||
});
|
||||
module.exports = __toCommonJS(expectUtils_exports);
|
||||
var import_rtti = require("../../utils/isomorphic/rtti");
|
||||
var import_utilsBundle = require("../../utilsBundle");
|
||||
function serializeExpectedTextValues(items, options = {}) {
|
||||
return items.map((i) => ({
|
||||
string: (0, import_rtti.isString)(i) ? i : void 0,
|
||||
@@ -32,7 +38,86 @@ function serializeExpectedTextValues(items, options = {}) {
|
||||
normalizeWhiteSpace: options.normalizeWhiteSpace
|
||||
}));
|
||||
}
|
||||
const printSubstring = (val) => val.replace(/"|\\/g, "\\$&");
|
||||
const printReceivedStringContainExpectedSubstring = (utils, received, start, length) => utils.RECEIVED_COLOR(
|
||||
'"' + printSubstring(received.slice(0, start)) + utils.INVERTED_COLOR(printSubstring(received.slice(start, start + length))) + printSubstring(received.slice(start + length)) + '"'
|
||||
);
|
||||
const printReceivedStringContainExpectedResult = (utils, received, result) => result === null ? utils.printReceived(received) : printReceivedStringContainExpectedSubstring(
|
||||
utils,
|
||||
received,
|
||||
result.index,
|
||||
result[0].length
|
||||
);
|
||||
function formatMatcherMessage(utils, details) {
|
||||
const receiver = details.receiver ?? (details.locator ? "locator" : "page");
|
||||
let message = utils.DIM_COLOR("expect(") + utils.RECEIVED_COLOR(receiver) + utils.DIM_COLOR(")" + (details.promise ? "." + details.promise : "") + (details.isNot ? ".not" : "") + ".") + details.matcherName + utils.DIM_COLOR("(") + utils.EXPECTED_COLOR(details.expectation) + utils.DIM_COLOR(")") + " failed\n\n";
|
||||
const diffLines = details.printedDiff?.split("\n");
|
||||
if (diffLines?.length === 2) {
|
||||
details.printedExpected = diffLines[0];
|
||||
details.printedReceived = diffLines[1];
|
||||
details.printedDiff = void 0;
|
||||
}
|
||||
const align = !details.errorMessage && details.printedExpected?.startsWith("Expected:") && (!details.printedReceived || details.printedReceived.startsWith("Received:"));
|
||||
if (details.locator)
|
||||
message += `Locator: ${align ? " " : ""}${details.locator}
|
||||
`;
|
||||
if (details.printedExpected)
|
||||
message += details.printedExpected + "\n";
|
||||
if (details.printedReceived)
|
||||
message += details.printedReceived + "\n";
|
||||
if (details.timedOut && details.timeout)
|
||||
message += `Timeout: ${align ? " " : ""}${details.timeout}ms
|
||||
`;
|
||||
if (details.printedDiff)
|
||||
message += details.printedDiff + "\n";
|
||||
if (details.errorMessage) {
|
||||
message += details.errorMessage;
|
||||
if (!details.errorMessage.endsWith("\n"))
|
||||
message += "\n";
|
||||
}
|
||||
message += callLogText(utils, details.log);
|
||||
return message;
|
||||
}
|
||||
const callLogText = (utils, log) => {
|
||||
if (!log || !log.some((l) => !!l))
|
||||
return "";
|
||||
return `
|
||||
Call log:
|
||||
${utils.DIM_COLOR(log.join("\n"))}
|
||||
`;
|
||||
};
|
||||
function printValue(value) {
|
||||
try {
|
||||
return JSON.stringify(value);
|
||||
} catch {
|
||||
return String(value);
|
||||
}
|
||||
}
|
||||
function printReceived(value) {
|
||||
return import_utilsBundle.colors.red(printValue(value));
|
||||
}
|
||||
function printExpected(value) {
|
||||
return import_utilsBundle.colors.green(printValue(value));
|
||||
}
|
||||
const simpleMatcherUtils = {
|
||||
DIM_COLOR: import_utilsBundle.colors.dim,
|
||||
RECEIVED_COLOR: import_utilsBundle.colors.red,
|
||||
EXPECTED_COLOR: import_utilsBundle.colors.green,
|
||||
INVERTED_COLOR: import_utilsBundle.colors.inverse,
|
||||
printReceived,
|
||||
printExpected,
|
||||
printDiffOrStringify: (expected, received, expectedLabel, receivedLabel) => {
|
||||
const maxLength = Math.max(expectedLabel.length, receivedLabel.length) + 2;
|
||||
return `${expectedLabel}: `.padEnd(maxLength) + printExpected(expected) + `
|
||||
` + `${receivedLabel}: `.padEnd(maxLength) + printReceived(received);
|
||||
}
|
||||
};
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
serializeExpectedTextValues
|
||||
callLogText,
|
||||
formatMatcherMessage,
|
||||
printReceivedStringContainExpectedResult,
|
||||
printReceivedStringContainExpectedSubstring,
|
||||
serializeExpectedTextValues,
|
||||
simpleMatcherUtils
|
||||
});
|
||||
|
||||
15
node_modules/playwright-core/lib/server/utils/hostPlatform.js
generated
vendored
15
node_modules/playwright-core/lib/server/utils/hostPlatform.js
generated
vendored
@@ -28,11 +28,13 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var hostPlatform_exports = {};
|
||||
__export(hostPlatform_exports, {
|
||||
hasGpuMac: () => hasGpuMac,
|
||||
hostPlatform: () => hostPlatform,
|
||||
isOfficiallySupportedPlatform: () => isOfficiallySupportedPlatform,
|
||||
shortPlatform: () => shortPlatform
|
||||
});
|
||||
module.exports = __toCommonJS(hostPlatform_exports);
|
||||
var import_child_process = require("child_process");
|
||||
var import_os = __toESM(require("os"));
|
||||
var import_linuxUtils = require("./linuxUtils");
|
||||
function calculatePlatform() {
|
||||
@@ -115,8 +117,21 @@ function toShortPlatform(hostPlatform2) {
|
||||
return hostPlatform2.endsWith("arm64") ? "linux-arm64" : "linux-x64";
|
||||
}
|
||||
const shortPlatform = toShortPlatform(hostPlatform);
|
||||
let hasGpuMacValue;
|
||||
function hasGpuMac() {
|
||||
try {
|
||||
if (hasGpuMacValue === void 0) {
|
||||
const output = (0, import_child_process.execSync)("system_profiler SPDisplaysDataType", { stdio: ["ignore", "pipe", "ignore"] }).toString();
|
||||
hasGpuMacValue = output.includes("Metal: Supported") || output.includes("Metal Support: Metal");
|
||||
}
|
||||
return hasGpuMacValue;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
hasGpuMac,
|
||||
hostPlatform,
|
||||
isOfficiallySupportedPlatform,
|
||||
shortPlatform
|
||||
|
||||
25
node_modules/playwright-core/lib/server/utils/httpServer.js
generated
vendored
25
node_modules/playwright-core/lib/server/utils/httpServer.js
generated
vendored
@@ -36,7 +36,6 @@ var import_path = __toESM(require("path"));
|
||||
var import_utilsBundle = require("../../utilsBundle");
|
||||
var import_crypto = require("./crypto");
|
||||
var import_assert = require("../../utils/isomorphic/assert");
|
||||
var import_manualPromise = require("../../utils/isomorphic/manualPromise");
|
||||
var import_network = require("./network");
|
||||
class HttpServer {
|
||||
constructor() {
|
||||
@@ -59,20 +58,6 @@ class HttpServer {
|
||||
port() {
|
||||
return this._port;
|
||||
}
|
||||
async _tryStart(port, host) {
|
||||
const errorPromise = new import_manualPromise.ManualPromise();
|
||||
const errorListener = (error) => errorPromise.reject(error);
|
||||
this._server.on("error", errorListener);
|
||||
try {
|
||||
this._server.listen(port, host);
|
||||
await Promise.race([
|
||||
new Promise((cb) => this._server.once("listening", cb)),
|
||||
errorPromise
|
||||
]);
|
||||
} finally {
|
||||
this._server.removeListener("error", errorListener);
|
||||
}
|
||||
}
|
||||
createWebSocket(transport, guid) {
|
||||
(0, import_assert.assert)(!this._wsGuid, "can only create one main websocket transport per server");
|
||||
this._wsGuid = guid || (0, import_crypto.createGuid)();
|
||||
@@ -100,17 +85,17 @@ class HttpServer {
|
||||
async start(options = {}) {
|
||||
(0, import_assert.assert)(!this._started, "server already started");
|
||||
this._started = true;
|
||||
const host = options.host || "localhost";
|
||||
const host = options.host;
|
||||
if (options.preferredPort) {
|
||||
try {
|
||||
await this._tryStart(options.preferredPort, host);
|
||||
await (0, import_network.startHttpServer)(this._server, { port: options.preferredPort, host });
|
||||
} catch (e) {
|
||||
if (!e || !e.message || !e.message.includes("EADDRINUSE"))
|
||||
throw e;
|
||||
await this._tryStart(void 0, host);
|
||||
await (0, import_network.startHttpServer)(this._server, { host });
|
||||
}
|
||||
} else {
|
||||
await this._tryStart(options.port, host);
|
||||
await (0, import_network.startHttpServer)(this._server, { port: options.port, host });
|
||||
}
|
||||
const address = this._server.address();
|
||||
(0, import_assert.assert)(address, "Could not bind server socket");
|
||||
@@ -121,7 +106,7 @@ class HttpServer {
|
||||
this._port = address.port;
|
||||
const resolvedHost = address.family === "IPv4" ? address.address : `[${address.address}]`;
|
||||
this._urlPrefixPrecise = `http://${resolvedHost}:${address.port}`;
|
||||
this._urlPrefixHumanReadable = `http://${host}:${address.port}`;
|
||||
this._urlPrefixHumanReadable = `http://${host ?? "localhost"}:${address.port}`;
|
||||
}
|
||||
}
|
||||
async stop() {
|
||||
|
||||
65
node_modules/playwright-core/lib/server/utils/network.js
generated
vendored
65
node_modules/playwright-core/lib/server/utils/network.js
generated
vendored
@@ -35,22 +35,20 @@ __export(network_exports, {
|
||||
createProxyAgent: () => createProxyAgent,
|
||||
fetchData: () => fetchData,
|
||||
httpRequest: () => httpRequest,
|
||||
isURLAvailable: () => isURLAvailable
|
||||
isURLAvailable: () => isURLAvailable,
|
||||
startHttpServer: () => startHttpServer
|
||||
});
|
||||
module.exports = __toCommonJS(network_exports);
|
||||
var import_http = __toESM(require("http"));
|
||||
var import_http2 = __toESM(require("http2"));
|
||||
var import_https = __toESM(require("https"));
|
||||
var import_url = __toESM(require("url"));
|
||||
var import_utilsBundle = require("../../utilsBundle");
|
||||
var import_happyEyeballs = require("./happyEyeballs");
|
||||
var import_manualPromise = require("../../utils/isomorphic/manualPromise");
|
||||
const NET_DEFAULT_TIMEOUT = 3e4;
|
||||
function httpRequest(params, onResponse, onError) {
|
||||
const parsedUrl = import_url.default.parse(params.url);
|
||||
let options = {
|
||||
...parsedUrl,
|
||||
agent: parsedUrl.protocol === "https:" ? import_happyEyeballs.httpsHappyEyeballsAgent : import_happyEyeballs.httpHappyEyeballsAgent,
|
||||
let url = new URL(params.url);
|
||||
const options = {
|
||||
method: params.method || "GET",
|
||||
headers: params.headers
|
||||
};
|
||||
@@ -58,21 +56,16 @@ function httpRequest(params, onResponse, onError) {
|
||||
options.rejectUnauthorized = params.rejectUnauthorized;
|
||||
const proxyURL = (0, import_utilsBundle.getProxyForUrl)(params.url);
|
||||
if (proxyURL) {
|
||||
const parsedProxyURL = normalizeProxyURL(proxyURL);
|
||||
if (params.url.startsWith("http:")) {
|
||||
const parsedProxyURL = import_url.default.parse(proxyURL);
|
||||
options = {
|
||||
path: parsedUrl.href,
|
||||
host: parsedProxyURL.hostname,
|
||||
port: parsedProxyURL.port,
|
||||
protocol: parsedProxyURL.protocol || "http:",
|
||||
headers: options.headers,
|
||||
method: options.method
|
||||
};
|
||||
parsedProxyURL.pathname = url.toString();
|
||||
url = parsedProxyURL;
|
||||
} else {
|
||||
options.agent = new import_utilsBundle.HttpsProxyAgent(normalizeProxyURL(proxyURL));
|
||||
options.agent = new import_utilsBundle.HttpsProxyAgent(parsedProxyURL);
|
||||
options.rejectUnauthorized = false;
|
||||
}
|
||||
}
|
||||
options.agent ??= url.protocol === "https:" ? import_happyEyeballs.httpsHappyEyeballsAgent : import_happyEyeballs.httpHappyEyeballsAgent;
|
||||
let cancelRequest;
|
||||
const requestCallback = (res) => {
|
||||
const statusCode = res.statusCode || 0;
|
||||
@@ -83,7 +76,7 @@ function httpRequest(params, onResponse, onError) {
|
||||
onResponse(res);
|
||||
}
|
||||
};
|
||||
const request = options.protocol === "https:" ? import_https.default.request(options, requestCallback) : import_http.default.request(options, requestCallback);
|
||||
const request = url.protocol === "https:" ? import_https.default.request(url, options, requestCallback) : import_http.default.request(url, options, requestCallback);
|
||||
request.on("error", onError);
|
||||
if (params.socketTimeout !== void 0) {
|
||||
request.setTimeout(params.socketTimeout, () => {
|
||||
@@ -122,7 +115,7 @@ async function fetchData(progress, params, onError) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
function shouldBypassProxy(url2, bypass) {
|
||||
function shouldBypassProxy(url, bypass) {
|
||||
if (!bypass)
|
||||
return false;
|
||||
const domains = bypass.split(",").map((s) => {
|
||||
@@ -131,7 +124,7 @@ function shouldBypassProxy(url2, bypass) {
|
||||
s = "." + s;
|
||||
return s;
|
||||
});
|
||||
const domain = "." + url2.hostname;
|
||||
const domain = "." + url.hostname;
|
||||
return domains.some((d) => domain.endsWith(d));
|
||||
}
|
||||
function normalizeProxyURL(proxy) {
|
||||
@@ -177,20 +170,35 @@ function createHttp2Server(...args) {
|
||||
decorateServer(server);
|
||||
return server;
|
||||
}
|
||||
async function isURLAvailable(url2, ignoreHTTPSErrors, onLog, onStdErr) {
|
||||
let statusCode = await httpStatusCode(url2, ignoreHTTPSErrors, onLog, onStdErr);
|
||||
if (statusCode === 404 && url2.pathname === "/") {
|
||||
const indexUrl = new URL(url2);
|
||||
async function startHttpServer(server, options) {
|
||||
const { host = "localhost", port = 0 } = options;
|
||||
const errorPromise = new import_manualPromise.ManualPromise();
|
||||
const errorListener = (error) => errorPromise.reject(error);
|
||||
server.on("error", errorListener);
|
||||
try {
|
||||
server.listen(port, host);
|
||||
await Promise.race([
|
||||
new Promise((cb) => server.once("listening", cb)),
|
||||
errorPromise
|
||||
]);
|
||||
} finally {
|
||||
server.removeListener("error", errorListener);
|
||||
}
|
||||
}
|
||||
async function isURLAvailable(url, ignoreHTTPSErrors, onLog, onStdErr) {
|
||||
let statusCode = await httpStatusCode(url, ignoreHTTPSErrors, onLog, onStdErr);
|
||||
if (statusCode === 404 && url.pathname === "/") {
|
||||
const indexUrl = new URL(url);
|
||||
indexUrl.pathname = "/index.html";
|
||||
statusCode = await httpStatusCode(indexUrl, ignoreHTTPSErrors, onLog, onStdErr);
|
||||
}
|
||||
return statusCode >= 200 && statusCode < 404;
|
||||
}
|
||||
async function httpStatusCode(url2, ignoreHTTPSErrors, onLog, onStdErr) {
|
||||
async function httpStatusCode(url, ignoreHTTPSErrors, onLog, onStdErr) {
|
||||
return new Promise((resolve) => {
|
||||
onLog?.(`HTTP GET: ${url2}`);
|
||||
onLog?.(`HTTP GET: ${url}`);
|
||||
httpRequest({
|
||||
url: url2.toString(),
|
||||
url: url.toString(),
|
||||
headers: { Accept: "*/*" },
|
||||
rejectUnauthorized: !ignoreHTTPSErrors
|
||||
}, (res) => {
|
||||
@@ -201,7 +209,7 @@ async function httpStatusCode(url2, ignoreHTTPSErrors, onLog, onStdErr) {
|
||||
}, (error) => {
|
||||
if (error.code === "DEPTH_ZERO_SELF_SIGNED_CERT")
|
||||
onStdErr?.(`[WebServer] Self-signed certificate detected. Try adding ignoreHTTPSErrors: true to config.webServer.`);
|
||||
onLog?.(`Error while checking if ${url2} is available: ${error.message}`);
|
||||
onLog?.(`Error while checking if ${url} is available: ${error.message}`);
|
||||
resolve(0);
|
||||
});
|
||||
});
|
||||
@@ -229,5 +237,6 @@ function decorateServer(server) {
|
||||
createProxyAgent,
|
||||
fetchData,
|
||||
httpRequest,
|
||||
isURLAvailable
|
||||
isURLAvailable,
|
||||
startHttpServer
|
||||
});
|
||||
|
||||
6
node_modules/playwright-core/lib/server/utils/nodePlatform.js
generated
vendored
6
node_modules/playwright-core/lib/server/utils/nodePlatform.js
generated
vendored
@@ -42,6 +42,7 @@ var import_utilsBundle = require("../../utilsBundle");
|
||||
var import_debugLogger = require("./debugLogger");
|
||||
var import_zones = require("./zones");
|
||||
var import_debug = require("./debug");
|
||||
var import_mcpBundle = require("../../mcpBundle");
|
||||
const pipelineAsync = util.promisify(import_stream.pipeline);
|
||||
class NodeZone {
|
||||
constructor(zone) {
|
||||
@@ -105,6 +106,11 @@ const nodePlatform = {
|
||||
streamWritable: (channel) => {
|
||||
return new WritableStreamImpl(channel);
|
||||
},
|
||||
zodToJsonSchema: (schema) => {
|
||||
if ("_zod" in schema)
|
||||
return import_mcpBundle.z.toJSONSchema(schema);
|
||||
return (0, import_mcpBundle.zodToJsonSchema)(schema);
|
||||
},
|
||||
zones: {
|
||||
current: () => new NodeZone((0, import_zones.currentZone)()),
|
||||
empty: new NodeZone(import_zones.emptyZone)
|
||||
|
||||
35
node_modules/playwright-core/lib/server/chromium/videoRecorder.js → node_modules/playwright-core/lib/server/videoRecorder.js
generated
vendored
Executable file → Normal file
35
node_modules/playwright-core/lib/server/chromium/videoRecorder.js → node_modules/playwright-core/lib/server/videoRecorder.js
generated
vendored
Executable file → Normal file
@@ -21,12 +21,11 @@ __export(videoRecorder_exports, {
|
||||
VideoRecorder: () => VideoRecorder
|
||||
});
|
||||
module.exports = __toCommonJS(videoRecorder_exports);
|
||||
var import_utils = require("../../utils");
|
||||
var import_page = require("../page");
|
||||
var import_processLauncher = require("../utils/processLauncher");
|
||||
var import_utils = require("../utils");
|
||||
var import_processLauncher = require("./utils/processLauncher");
|
||||
const fps = 25;
|
||||
class VideoRecorder {
|
||||
constructor(page, ffmpegPath) {
|
||||
constructor(ffmpegPath, options) {
|
||||
this._process = null;
|
||||
this._gracefullyClose = null;
|
||||
this._lastWritePromise = Promise.resolve();
|
||||
@@ -36,16 +35,12 @@ class VideoRecorder {
|
||||
this._frameQueue = [];
|
||||
this._isStopped = false;
|
||||
this._ffmpegPath = ffmpegPath;
|
||||
page.on(import_page.Page.Events.ScreencastFrame, (frame) => this.writeFrame(frame.buffer, frame.frameSwapWallTime / 1e3));
|
||||
}
|
||||
static async launch(page, ffmpegPath, options) {
|
||||
if (!options.outputFile.endsWith(".webm"))
|
||||
throw new Error("File must have .webm extension");
|
||||
const recorder = new VideoRecorder(page, ffmpegPath);
|
||||
await recorder._launch(options);
|
||||
return recorder;
|
||||
this._launchPromise = this._launch(options).catch((e) => e);
|
||||
}
|
||||
async _launch(options) {
|
||||
await (0, import_utils.mkdirIfNeeded)(options.outputFile);
|
||||
const w = options.width;
|
||||
const h = options.height;
|
||||
const args = `-loglevel error -f image2pipe -avioflags direct -fpsprobesize 0 -probesize 32 -analyzeduration 0 -c:v mjpeg -i pipe:0 -y -an -r ${fps} -c:v vp8 -qmin 0 -qmax 50 -crf 8 -deadline realtime -speed 8 -b:v 1M -threads 1 -vf pad=${w}:${h}:0:0:gray,crop=${w}:${h}:0:0`.split(" ");
|
||||
@@ -74,6 +69,13 @@ class VideoRecorder {
|
||||
this._gracefullyClose = gracefullyClose;
|
||||
}
|
||||
writeFrame(frame, timestamp) {
|
||||
this._launchPromise.then((error) => {
|
||||
if (error)
|
||||
return;
|
||||
this._writeFrame(frame, timestamp);
|
||||
});
|
||||
}
|
||||
_writeFrame(frame, timestamp) {
|
||||
(0, import_utils.assert)(this._process);
|
||||
if (this._isStopped)
|
||||
return;
|
||||
@@ -100,13 +102,20 @@ class VideoRecorder {
|
||||
});
|
||||
}
|
||||
async stop() {
|
||||
const error = await this._launchPromise;
|
||||
if (error)
|
||||
throw error;
|
||||
if (this._isStopped || !this._lastFrame)
|
||||
return;
|
||||
const addTime = Math.max(((0, import_utils.monotonicTime)() - this._lastWriteNodeTime) / 1e3, 1);
|
||||
this.writeFrame(Buffer.from([]), this._lastFrame.timestamp + addTime);
|
||||
this._writeFrame(Buffer.from([]), this._lastFrame.timestamp + addTime);
|
||||
this._isStopped = true;
|
||||
await this._lastWritePromise;
|
||||
await this._gracefullyClose();
|
||||
try {
|
||||
await this._lastWritePromise;
|
||||
await this._gracefullyClose();
|
||||
} catch (e) {
|
||||
import_utils.debugLogger.log("error", `ffmpeg failed to stop: ${String(e)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
10
node_modules/playwright-core/lib/server/webkit/webkit.js
generated
vendored
10
node_modules/playwright-core/lib/server/webkit/webkit.js
generated
vendored
@@ -51,12 +51,10 @@ class WebKit extends import_browserType.BrowserType {
|
||||
CURL_COOKIE_JAR_PATH: process.platform === "win32" && isPersistent ? import_path.default.join(userDataDir, "cookiejar.db") : void 0
|
||||
};
|
||||
}
|
||||
doRewriteStartupLog(error) {
|
||||
if (!error.logs)
|
||||
return error;
|
||||
if (error.logs.includes("Failed to open display") || error.logs.includes("cannot open display"))
|
||||
error.logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
|
||||
return error;
|
||||
doRewriteStartupLog(logs) {
|
||||
if (logs.includes("Failed to open display") || logs.includes("cannot open display"))
|
||||
logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
|
||||
return logs;
|
||||
}
|
||||
attemptToGracefullyCloseBrowser(transport) {
|
||||
transport.send({ method: "Playwright.close", params: {}, id: import_wkConnection.kBrowserCloseMessageId });
|
||||
|
||||
8
node_modules/playwright-core/lib/server/webkit/wkBrowser.js
generated
vendored
8
node_modules/playwright-core/lib/server/webkit/wkBrowser.js
generated
vendored
@@ -56,7 +56,6 @@ class WKBrowser extends import_browser.Browser {
|
||||
this._browserSession.on("Playwright.downloadCreated", this._onDownloadCreated.bind(this));
|
||||
this._browserSession.on("Playwright.downloadFilenameSuggested", this._onDownloadFilenameSuggested.bind(this));
|
||||
this._browserSession.on("Playwright.downloadFinished", this._onDownloadFinished.bind(this));
|
||||
this._browserSession.on("Playwright.screencastFinished", this._onScreencastFinished.bind(this));
|
||||
this._browserSession.on(import_wkConnection.kPageProxyMessageReceived, this._onPageProxyMessageReceived.bind(this));
|
||||
}
|
||||
static async connect(parent, transport, options) {
|
||||
@@ -79,7 +78,7 @@ class WKBrowser extends import_browser.Browser {
|
||||
wkPage.didClose();
|
||||
this._wkPages.clear();
|
||||
for (const video of this._idToVideo.values())
|
||||
video.artifact.reportFinished(new import_errors.TargetClosedError());
|
||||
video.artifact.reportFinished(new import_errors.TargetClosedError(this.closeReason()));
|
||||
this._idToVideo.clear();
|
||||
this._didClose();
|
||||
}
|
||||
@@ -131,9 +130,6 @@ class WKBrowser extends import_browser.Browser {
|
||||
_onDownloadFinished(payload) {
|
||||
this._downloadFinished(payload.uuid, payload.error);
|
||||
}
|
||||
_onScreencastFinished(payload) {
|
||||
this._takeVideo(payload.screencastId)?.reportFinished();
|
||||
}
|
||||
_onPageProxyCreated(event) {
|
||||
const pageProxyId = event.pageProxyId;
|
||||
let context = null;
|
||||
@@ -315,7 +311,7 @@ class WKBrowserContext extends import_browserContext.BrowserContext {
|
||||
}
|
||||
async doClose(reason) {
|
||||
if (!this._browserContextId) {
|
||||
await Promise.all(this._wkPages().map((wkPage) => wkPage._stopVideo()));
|
||||
await Promise.all(this._wkPages().map((wkPage) => wkPage._page.screencast.stopVideoRecording()));
|
||||
await this._browser.close({ reason });
|
||||
} else {
|
||||
await this._browser._browserSession.send("Playwright.deleteContext", { browserContextId: this._browserContextId });
|
||||
|
||||
7
node_modules/playwright-core/lib/server/webkit/wkConnection.js
generated
vendored
7
node_modules/playwright-core/lib/server/webkit/wkConnection.js
generated
vendored
@@ -89,11 +89,6 @@ class WKSession extends import_events.EventEmitter {
|
||||
this.connection = connection;
|
||||
this.sessionId = sessionId;
|
||||
this._rawSend = rawSend;
|
||||
this.on = super.on;
|
||||
this.off = super.removeListener;
|
||||
this.addListener = super.addListener;
|
||||
this.removeListener = super.removeListener;
|
||||
this.once = super.once;
|
||||
}
|
||||
async send(method, params) {
|
||||
if (this._crashed || this._disposed || this.connection._browserDisconnectedLogs)
|
||||
@@ -134,7 +129,7 @@ class WKSession extends import_events.EventEmitter {
|
||||
callback.resolve(object.result);
|
||||
}
|
||||
} else if (object.id && !object.error) {
|
||||
(0, import_utils.assert)(this.isDisposed());
|
||||
(0, import_utils.assert)(this.isDisposed(), JSON.stringify(object));
|
||||
} else {
|
||||
Promise.resolve().then(() => this.emit(object.method, object.params));
|
||||
}
|
||||
|
||||
30
node_modules/playwright-core/lib/server/webkit/wkInterceptableRequest.js
generated
vendored
30
node_modules/playwright-core/lib/server/webkit/wkInterceptableRequest.js
generated
vendored
@@ -54,7 +54,7 @@ class WKInterceptableRequest {
|
||||
constructor(session, frame, event, redirectedFrom, documentId) {
|
||||
this._session = session;
|
||||
this._requestId = event.requestId;
|
||||
const resourceType = event.type ? event.type.toLowerCase() : redirectedFrom ? redirectedFrom.request.resourceType() : "other";
|
||||
const resourceType = event.type ? toResourceType(event.type) : redirectedFrom ? redirectedFrom.request.resourceType() : "other";
|
||||
let postDataBuffer = null;
|
||||
this._timestamp = event.timestamp;
|
||||
this._wallTime = event.walltime * 1e3;
|
||||
@@ -162,6 +162,34 @@ function wkMillisToRoundishMillis(value) {
|
||||
}
|
||||
return (value * 1e3 | 0) / 1e3;
|
||||
}
|
||||
function toResourceType(type) {
|
||||
switch (type) {
|
||||
case "Document":
|
||||
return "document";
|
||||
case "StyleSheet":
|
||||
return "stylesheet";
|
||||
case "Image":
|
||||
return "image";
|
||||
case "Font":
|
||||
return "font";
|
||||
case "Script":
|
||||
return "script";
|
||||
case "XHR":
|
||||
return "xhr";
|
||||
case "Fetch":
|
||||
return "fetch";
|
||||
case "Ping":
|
||||
return "ping";
|
||||
case "Beacon":
|
||||
return "beacon";
|
||||
case "WebSocket":
|
||||
return "websocket";
|
||||
case "EventSource":
|
||||
return "eventsource";
|
||||
default:
|
||||
return "other";
|
||||
}
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
WKInterceptableRequest,
|
||||
|
||||
121
node_modules/playwright-core/lib/server/webkit/wkPage.js
generated
vendored
121
node_modules/playwright-core/lib/server/webkit/wkPage.js
generated
vendored
@@ -31,10 +31,8 @@ __export(wkPage_exports, {
|
||||
WKPage: () => WKPage
|
||||
});
|
||||
module.exports = __toCommonJS(wkPage_exports);
|
||||
var import_path = __toESM(require("path"));
|
||||
var import_utils = require("../../utils");
|
||||
var import_headers = require("../../utils/isomorphic/headers");
|
||||
var import_crypto = require("../utils/crypto");
|
||||
var import_eventsHelper = require("../utils/eventsHelper");
|
||||
var import_hostPlatform = require("../utils/hostPlatform");
|
||||
var import_stackTrace = require("../../utils/isomorphic/stackTrace");
|
||||
@@ -51,12 +49,14 @@ var import_wkInput = require("./wkInput");
|
||||
var import_wkInterceptableRequest = require("./wkInterceptableRequest");
|
||||
var import_wkProvisionalPage = require("./wkProvisionalPage");
|
||||
var import_wkWorkers = require("./wkWorkers");
|
||||
var import_debugLogger = require("../utils/debugLogger");
|
||||
var import_webkit = require("./webkit");
|
||||
var import_registry = require("../registry");
|
||||
const UTILITY_WORLD_NAME = "__playwright_utility_world__";
|
||||
const enableFrameSessions = !process.env.WK_DISABLE_FRAME_SESSIONS && parseInt(import_registry.registry.findExecutable("webkit").revision, 10) >= 2245;
|
||||
class WKPage {
|
||||
constructor(browserContext, pageProxySession, opener) {
|
||||
this._provisionalPage = null;
|
||||
this._targetIdToFrameSession = /* @__PURE__ */ new Map();
|
||||
this._requestIdToRequest = /* @__PURE__ */ new Map();
|
||||
this._requestIdToRequestWillBeSentEvent = /* @__PURE__ */ new Map();
|
||||
this._sessionListeners = [];
|
||||
@@ -66,7 +66,6 @@ class WKPage {
|
||||
};
|
||||
this._lastConsoleMessage = null;
|
||||
this._requestIdToResponseReceivedPayloadEvent = /* @__PURE__ */ new Map();
|
||||
this._recordingVideoFile = null;
|
||||
this._screencastGeneration = 0;
|
||||
this._pageProxySession = pageProxySession;
|
||||
this._opener = opener;
|
||||
@@ -116,16 +115,7 @@ class WKPage {
|
||||
for (const [key, value] of this._browserContext._permissions)
|
||||
promises.push(this._grantPermissions(key, value));
|
||||
}
|
||||
if (this._browserContext._options.recordVideo) {
|
||||
const outputFile = import_path.default.join(this._browserContext._options.recordVideo.dir, (0, import_crypto.createGuid)() + ".webm");
|
||||
promises.push(this._browserContext._ensureVideosPath().then(() => {
|
||||
return this._startVideo({
|
||||
// validateBrowserContextOptions ensures correct video size.
|
||||
...this._browserContext._options.recordVideo.size,
|
||||
outputFile
|
||||
});
|
||||
}));
|
||||
}
|
||||
promises.push(this._initializeVideoRecording());
|
||||
await Promise.all(promises);
|
||||
}
|
||||
_setSession(session) {
|
||||
@@ -159,10 +149,13 @@ class WKPage {
|
||||
session.send("Page.createUserWorld", { name: UTILITY_WORLD_NAME }).catch((_) => {
|
||||
}),
|
||||
// Worlds are per-process
|
||||
session.send("Console.enable"),
|
||||
session.send("Network.enable"),
|
||||
this._workers.initializeSession(session)
|
||||
];
|
||||
if (enableFrameSessions)
|
||||
this._initializeFrameSessions(frameTree.frameTree, promises);
|
||||
else
|
||||
promises.push(session.send("Console.enable"));
|
||||
if (this._page.browserContext.needsPlaywrightBinding())
|
||||
promises.push(session.send("Runtime.addBinding", { name: import_page.PageBinding.kBindingName }));
|
||||
if (this._page.needsRequestInterception()) {
|
||||
@@ -219,6 +212,13 @@ class WKPage {
|
||||
promises.push(session.send("Page.overrideSetting", { setting: "FixedBackgroundsPaintRelativeToDocument", value: contextOptions.isMobile }));
|
||||
await Promise.all(promises);
|
||||
}
|
||||
_initializeFrameSessions(frame, promises) {
|
||||
const session = this._targetIdToFrameSession.get(`frame-${frame.frame.id}`);
|
||||
if (session)
|
||||
promises.push(session.initialize());
|
||||
for (const childFrame of frame.childFrames || [])
|
||||
this._initializeFrameSessions(childFrame, promises);
|
||||
}
|
||||
_onDidCommitProvisionalTarget(event) {
|
||||
const { oldTargetId, newTargetId } = event;
|
||||
(0, import_utils.assert)(this._provisionalPage);
|
||||
@@ -244,6 +244,9 @@ class WKPage {
|
||||
this._session.markAsCrashed();
|
||||
this._page._didCrash();
|
||||
}
|
||||
} else if (this._targetIdToFrameSession.has(targetId)) {
|
||||
this._targetIdToFrameSession.get(targetId).dispose();
|
||||
this._targetIdToFrameSession.delete(targetId);
|
||||
}
|
||||
}
|
||||
didClose() {
|
||||
@@ -257,7 +260,7 @@ class WKPage {
|
||||
this._provisionalPage.dispose();
|
||||
this._provisionalPage = null;
|
||||
}
|
||||
this._firstNonInitialNavigationCommittedReject(new import_errors.TargetClosedError());
|
||||
this._firstNonInitialNavigationCommittedReject(new import_errors.TargetClosedError(this._page.closeReason()));
|
||||
this._page._didClose();
|
||||
}
|
||||
dispatchMessageToSession(message) {
|
||||
@@ -288,8 +291,15 @@ class WKPage {
|
||||
session.dispatchMessage({ id: message.id, error: { message: e.message } });
|
||||
});
|
||||
});
|
||||
if (targetInfo.type === "frame")
|
||||
if (targetInfo.type === "frame") {
|
||||
if (enableFrameSessions) {
|
||||
const wkFrame = new WKFrame(this, session);
|
||||
this._targetIdToFrameSession.set(targetInfo.targetId, wkFrame);
|
||||
await wkFrame.initialize().catch((e) => {
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
(0, import_utils.assert)(targetInfo.type === "page", "Only page targets are expected in WebKit, received: " + targetInfo.type);
|
||||
if (!targetInfo.isProvisional) {
|
||||
(0, import_utils.assert)(!this._page.initializedOrUndefined());
|
||||
@@ -331,6 +341,8 @@ class WKPage {
|
||||
this._provisionalPage._session.dispatchMessage(JSON.parse(message));
|
||||
else if (this._session.sessionId === targetId)
|
||||
this._session.dispatchMessage(JSON.parse(message));
|
||||
else if (this._targetIdToFrameSession.has(targetId))
|
||||
this._targetIdToFrameSession.get(targetId)._session.dispatchMessage(JSON.parse(message));
|
||||
else
|
||||
throw new Error("Unknown target: " + targetId);
|
||||
}
|
||||
@@ -453,7 +465,7 @@ class WKPage {
|
||||
}
|
||||
async navigateFrame(frame, url, referrer) {
|
||||
if (this._pageProxySession.isDisposed())
|
||||
throw new import_errors.TargetClosedError();
|
||||
throw new import_errors.TargetClosedError(this._page.closeReason());
|
||||
const pageProxyId = this._pageProxySession.sessionId;
|
||||
const result = await this._pageProxySession.connection.browserSession.send("Playwright.navigate", { url, pageProxyId, frameId: frame._id, referrer });
|
||||
return { newDocumentId: result.loaderId };
|
||||
@@ -748,7 +760,6 @@ class WKPage {
|
||||
await this._updateState("Page.setBootstrapScript", { source: this._calculateBootstrapScript() });
|
||||
}
|
||||
async closePage(runBeforeUnload) {
|
||||
await this._stopVideo();
|
||||
await this._pageProxySession.sendMayFail("Target.close", {
|
||||
targetId: this._session.sessionId,
|
||||
runBeforeUnload
|
||||
@@ -762,22 +773,11 @@ class WKPage {
|
||||
return import_hostPlatform.hostPlatform === "mac10.15" ? 55 : 59;
|
||||
return 0;
|
||||
}
|
||||
async _startVideo(options) {
|
||||
(0, import_utils.assert)(!this._recordingVideoFile);
|
||||
const { screencastId } = await this._pageProxySession.send("Screencast.startVideo", {
|
||||
file: this._browserContext._browser.options.channel === "webkit-wsl" ? await (0, import_webkit.translatePathToWSL)(options.outputFile) : options.outputFile,
|
||||
width: options.width,
|
||||
height: options.height,
|
||||
toolbarHeight: this._toolbarHeight()
|
||||
});
|
||||
this._recordingVideoFile = options.outputFile;
|
||||
this._browserContext._browser._videoStarted(this._browserContext, screencastId, options.outputFile, this._page.waitForInitializedOrError());
|
||||
}
|
||||
async _stopVideo() {
|
||||
if (!this._recordingVideoFile)
|
||||
return;
|
||||
await this._pageProxySession.sendMayFail("Screencast.stopVideo");
|
||||
this._recordingVideoFile = null;
|
||||
async _initializeVideoRecording() {
|
||||
const screencast = this._page.screencast;
|
||||
const videoOptions = screencast.launchVideoRecorder();
|
||||
if (videoOptions)
|
||||
await screencast.startVideoRecording(videoOptions);
|
||||
}
|
||||
validateScreenshotDimension(side, omitDeviceScaleFactor) {
|
||||
if (process.platform === "darwin")
|
||||
@@ -845,23 +845,27 @@ class WKPage {
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
async setScreencastOptions(options) {
|
||||
if (options) {
|
||||
const so = { ...options, toolbarHeight: this._toolbarHeight() };
|
||||
const { generation } = await this._pageProxySession.send("Screencast.startScreencast", so);
|
||||
this._screencastGeneration = generation;
|
||||
} else {
|
||||
await this._pageProxySession.send("Screencast.stopScreencast");
|
||||
}
|
||||
async startScreencast(options) {
|
||||
const { generation } = await this._pageProxySession.send("Screencast.startScreencast", {
|
||||
quality: options.quality,
|
||||
width: options.width,
|
||||
height: options.height,
|
||||
toolbarHeight: this._toolbarHeight()
|
||||
});
|
||||
this._screencastGeneration = generation;
|
||||
}
|
||||
async stopScreencast() {
|
||||
await this._pageProxySession.sendMayFail("Screencast.stopScreencast");
|
||||
}
|
||||
_onScreencastFrame(event) {
|
||||
const generation = this._screencastGeneration;
|
||||
this._page.throttleScreencastFrameAck(() => {
|
||||
this._pageProxySession.send("Screencast.screencastFrameAck", { generation }).catch((e) => import_debugLogger.debugLogger.log("error", e));
|
||||
this._page.screencast.throttleFrameAck(() => {
|
||||
this._pageProxySession.sendMayFail("Screencast.screencastFrameAck", { generation });
|
||||
});
|
||||
const buffer = Buffer.from(event.data, "base64");
|
||||
this._page.emit(import_page.Page.Events.ScreencastFrame, {
|
||||
buffer,
|
||||
frameSwapWallTime: event.timestamp ? event.timestamp * 1e3 : Date.now(),
|
||||
width: event.deviceWidth,
|
||||
height: event.deviceHeight
|
||||
});
|
||||
@@ -886,7 +890,7 @@ class WKPage {
|
||||
const pageProxyId = this._pageProxySession.sessionId;
|
||||
const objectId = handle._objectId;
|
||||
if (this._browserContext._browser?.options.channel === "webkit-wsl")
|
||||
paths = await Promise.all(paths.map((path2) => (0, import_webkit.translatePathToWSL)(path2)));
|
||||
paths = await Promise.all(paths.map((path) => (0, import_webkit.translatePathToWSL)(path)));
|
||||
await Promise.all([
|
||||
this._pageProxySession.connection.browserSession.send("Playwright.grantFileReadAccess", { pageProxyId, paths }),
|
||||
this._session.send("DOM.setInputFiles", { objectId, paths })
|
||||
@@ -1085,6 +1089,31 @@ class WKPage {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class WKFrame {
|
||||
constructor(page, session) {
|
||||
this._sessionListeners = [];
|
||||
this._initializePromise = null;
|
||||
this._page = page;
|
||||
this._session = session;
|
||||
}
|
||||
async initialize() {
|
||||
if (this._initializePromise)
|
||||
return this._initializePromise;
|
||||
this._initializePromise = this._initializeImpl();
|
||||
return this._initializePromise;
|
||||
}
|
||||
async _initializeImpl() {
|
||||
this._sessionListeners = [
|
||||
import_eventsHelper.eventsHelper.addEventListener(this._session, "Console.messageAdded", (event) => this._page._onConsoleMessage(event)),
|
||||
import_eventsHelper.eventsHelper.addEventListener(this._session, "Console.messageRepeatCountUpdated", (event) => this._page._onConsoleRepeatCountUpdated(event))
|
||||
];
|
||||
await this._session.send("Console.enable");
|
||||
}
|
||||
dispose() {
|
||||
import_eventsHelper.eventsHelper.removeEventListeners(this._sessionListeners);
|
||||
this._session.dispose();
|
||||
}
|
||||
}
|
||||
function parseRemoteAddress(value) {
|
||||
if (!value)
|
||||
return;
|
||||
|
||||
2
node_modules/playwright-core/lib/utils.js
generated
vendored
2
node_modules/playwright-core/lib/utils.js
generated
vendored
@@ -39,6 +39,7 @@ __reExport(utils_exports, require("./utils/isomorphic/stringUtils"), module.expo
|
||||
__reExport(utils_exports, require("./utils/isomorphic/time"), module.exports);
|
||||
__reExport(utils_exports, require("./utils/isomorphic/timeoutRunner"), module.exports);
|
||||
__reExport(utils_exports, require("./utils/isomorphic/urlMatch"), module.exports);
|
||||
__reExport(utils_exports, require("./utils/isomorphic/yaml"), module.exports);
|
||||
__reExport(utils_exports, require("./server/utils/ascii"), module.exports);
|
||||
__reExport(utils_exports, require("./server/utils/comparators"), module.exports);
|
||||
__reExport(utils_exports, require("./server/utils/crypto"), module.exports);
|
||||
@@ -83,6 +84,7 @@ var import_utilsBundle = require("./utilsBundle");
|
||||
...require("./utils/isomorphic/time"),
|
||||
...require("./utils/isomorphic/timeoutRunner"),
|
||||
...require("./utils/isomorphic/urlMatch"),
|
||||
...require("./utils/isomorphic/yaml"),
|
||||
...require("./server/utils/ascii"),
|
||||
...require("./server/utils/comparators"),
|
||||
...require("./server/utils/crypto"),
|
||||
|
||||
62
node_modules/playwright-core/lib/utils/isomorphic/ariaSnapshot.js
generated
vendored
62
node_modules/playwright-core/lib/utils/isomorphic/ariaSnapshot.js
generated
vendored
@@ -20,12 +20,26 @@ var ariaSnapshot_exports = {};
|
||||
__export(ariaSnapshot_exports, {
|
||||
KeyParser: () => KeyParser,
|
||||
ParserError: () => ParserError,
|
||||
ariaPropsEqual: () => ariaPropsEqual,
|
||||
ariaNodesEqual: () => ariaNodesEqual,
|
||||
findNewNode: () => findNewNode,
|
||||
hasPointerCursor: () => hasPointerCursor,
|
||||
parseAriaSnapshot: () => parseAriaSnapshot,
|
||||
parseAriaSnapshotUnsafe: () => parseAriaSnapshotUnsafe,
|
||||
textValue: () => textValue
|
||||
});
|
||||
module.exports = __toCommonJS(ariaSnapshot_exports);
|
||||
function ariaNodesEqual(a, b) {
|
||||
if (a.role !== b.role || a.name !== b.name)
|
||||
return false;
|
||||
if (!ariaPropsEqual(a, b) || hasPointerCursor(a) !== hasPointerCursor(b))
|
||||
return false;
|
||||
const aKeys = Object.keys(a.props);
|
||||
const bKeys = Object.keys(b.props);
|
||||
return aKeys.length === bKeys.length && aKeys.every((k) => a.props[k] === b.props[k]);
|
||||
}
|
||||
function hasPointerCursor(ariaNode) {
|
||||
return ariaNode.box.cursor === "pointer";
|
||||
}
|
||||
function ariaPropsEqual(a, b) {
|
||||
return a.active === b.active && a.checked === b.checked && a.disabled === b.disabled && a.expanded === b.expanded && a.selected === b.selected && a.level === b.level && a.pressed === b.pressed;
|
||||
}
|
||||
@@ -386,11 +400,55 @@ class ParserError extends Error {
|
||||
this.pos = pos;
|
||||
}
|
||||
}
|
||||
function findNewNode(from, to) {
|
||||
function fillMap(root, map, position) {
|
||||
let size = 1;
|
||||
let childPosition = position + size;
|
||||
for (const child of root.children || []) {
|
||||
if (typeof child === "string") {
|
||||
size++;
|
||||
childPosition++;
|
||||
} else {
|
||||
size += fillMap(child, map, childPosition);
|
||||
childPosition += size;
|
||||
}
|
||||
}
|
||||
if (!["none", "presentation", "fragment", "iframe", "generic"].includes(root.role) && root.name) {
|
||||
let byRole = map.get(root.role);
|
||||
if (!byRole) {
|
||||
byRole = /* @__PURE__ */ new Map();
|
||||
map.set(root.role, byRole);
|
||||
}
|
||||
const existing = byRole.get(root.name);
|
||||
const sizeAndPosition = size * 100 - position;
|
||||
if (!existing || existing.sizeAndPosition < sizeAndPosition)
|
||||
byRole.set(root.name, { node: root, sizeAndPosition });
|
||||
}
|
||||
return size;
|
||||
}
|
||||
const fromMap = /* @__PURE__ */ new Map();
|
||||
if (from)
|
||||
fillMap(from, fromMap, 0);
|
||||
const toMap = /* @__PURE__ */ new Map();
|
||||
fillMap(to, toMap, 0);
|
||||
const result = [];
|
||||
for (const [role, byRole] of toMap) {
|
||||
for (const [name, byName] of byRole) {
|
||||
const inFrom = fromMap.get(role)?.get(name);
|
||||
if (!inFrom)
|
||||
result.push(byName);
|
||||
}
|
||||
}
|
||||
result.sort((a, b) => b.sizeAndPosition - a.sizeAndPosition);
|
||||
return result[0]?.node;
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
KeyParser,
|
||||
ParserError,
|
||||
ariaPropsEqual,
|
||||
ariaNodesEqual,
|
||||
findNewNode,
|
||||
hasPointerCursor,
|
||||
parseAriaSnapshot,
|
||||
parseAriaSnapshotUnsafe,
|
||||
textValue
|
||||
|
||||
51
node_modules/playwright-core/lib/utils/isomorphic/lruCache.js
generated
vendored
Normal file
51
node_modules/playwright-core/lib/utils/isomorphic/lruCache.js
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var lruCache_exports = {};
|
||||
__export(lruCache_exports, {
|
||||
LRUCache: () => LRUCache
|
||||
});
|
||||
module.exports = __toCommonJS(lruCache_exports);
|
||||
class LRUCache {
|
||||
constructor(maxSize) {
|
||||
this._maxSize = maxSize;
|
||||
this._map = /* @__PURE__ */ new Map();
|
||||
this._size = 0;
|
||||
}
|
||||
getOrCompute(key, compute) {
|
||||
if (this._map.has(key)) {
|
||||
const result2 = this._map.get(key);
|
||||
this._map.delete(key);
|
||||
this._map.set(key, result2);
|
||||
return result2.value;
|
||||
}
|
||||
const result = compute();
|
||||
while (this._map.size && this._size + result.size > this._maxSize) {
|
||||
const [firstKey, firstValue] = this._map.entries().next().value;
|
||||
this._size -= firstValue.size;
|
||||
this._map.delete(firstKey);
|
||||
}
|
||||
this._map.set(key, result);
|
||||
this._size += result.size;
|
||||
return result.value;
|
||||
}
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
LRUCache
|
||||
});
|
||||
10
node_modules/playwright-core/lib/utils/isomorphic/protocolMetainfo.js
generated
vendored
10
node_modules/playwright-core/lib/utils/isomorphic/protocolMetainfo.js
generated
vendored
@@ -71,6 +71,7 @@ const methodMetainfo = /* @__PURE__ */ new Map([
|
||||
["WebSocket.waitForEventInfo", { title: 'Wait for event "{info.event}"', snapshot: true }],
|
||||
["ElectronApplication.waitForEventInfo", { title: 'Wait for event "{info.event}"', snapshot: true }],
|
||||
["AndroidDevice.waitForEventInfo", { title: 'Wait for event "{info.event}"', snapshot: true }],
|
||||
["PageAgent.waitForEventInfo", { title: 'Wait for event "{info.event}"', snapshot: true }],
|
||||
["BrowserContext.addCookies", { title: "Add cookies", group: "configuration" }],
|
||||
["BrowserContext.addInitScript", { title: "Add init script", group: "configuration" }],
|
||||
["BrowserContext.clearCookies", { title: "Clear cookies", group: "configuration" }],
|
||||
@@ -92,6 +93,7 @@ const methodMetainfo = /* @__PURE__ */ new Map([
|
||||
["BrowserContext.pause", { title: "Pause" }],
|
||||
["BrowserContext.enableRecorder", { internal: true }],
|
||||
["BrowserContext.disableRecorder", { internal: true }],
|
||||
["BrowserContext.exposeConsoleApi", { internal: true }],
|
||||
["BrowserContext.newCDPSession", { title: "Create CDP session", group: "configuration" }],
|
||||
["BrowserContext.harStart", { internal: true }],
|
||||
["BrowserContext.harExport", { internal: true }],
|
||||
@@ -143,6 +145,7 @@ const methodMetainfo = /* @__PURE__ */ new Map([
|
||||
["Page.stopCSSCoverage", { title: "Stop CSS coverage", group: "configuration" }],
|
||||
["Page.bringToFront", { title: "Bring to front" }],
|
||||
["Page.updateSubscription", { internal: true }],
|
||||
["Page.agent", { internal: true }],
|
||||
["Frame.evalOnSelector", { title: "Evaluate", snapshot: true, pausesBeforeAction: true }],
|
||||
["Frame.evalOnSelectorAll", { title: "Evaluate", snapshot: true, pausesBeforeAction: true }],
|
||||
["Frame.addScriptTag", { title: "Add script tag", snapshot: true, pausesBeforeAction: true }],
|
||||
@@ -314,7 +317,12 @@ const methodMetainfo = /* @__PURE__ */ new Map([
|
||||
["AndroidDevice.connectToWebView", { title: "Connect to Web View" }],
|
||||
["AndroidDevice.close", { internal: true }],
|
||||
["JsonPipe.send", { internal: true }],
|
||||
["JsonPipe.close", { internal: true }]
|
||||
["JsonPipe.close", { internal: true }],
|
||||
["PageAgent.perform", { title: 'Perform "{task}"' }],
|
||||
["PageAgent.expect", { title: 'Expect "{expectation}"' }],
|
||||
["PageAgent.extract", { title: 'Extract "{query}"' }],
|
||||
["PageAgent.dispose", { internal: true }],
|
||||
["PageAgent.usage", { title: "Get agent usage", group: "configuration" }]
|
||||
]);
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
|
||||
49
node_modules/playwright-core/lib/utils/isomorphic/stringUtils.js
generated
vendored
49
node_modules/playwright-core/lib/utils/isomorphic/stringUtils.js
generated
vendored
@@ -18,6 +18,7 @@ var __copyProps = (to, from, except, desc) => {
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var stringUtils_exports = {};
|
||||
__export(stringUtils_exports, {
|
||||
ansiRegex: () => ansiRegex,
|
||||
cacheNormalizedWhitespaces: () => cacheNormalizedWhitespaces,
|
||||
escapeForAttributeSelector: () => escapeForAttributeSelector,
|
||||
escapeForTextSelector: () => escapeForTextSelector,
|
||||
@@ -26,11 +27,15 @@ __export(stringUtils_exports, {
|
||||
escapeRegExp: () => escapeRegExp,
|
||||
escapeTemplateString: () => escapeTemplateString,
|
||||
escapeWithQuotes: () => escapeWithQuotes,
|
||||
formatObject: () => formatObject,
|
||||
formatObjectOrVoid: () => formatObjectOrVoid,
|
||||
isString: () => isString,
|
||||
longestCommonSubstring: () => longestCommonSubstring,
|
||||
normalizeEscapedRegexQuotes: () => normalizeEscapedRegexQuotes,
|
||||
normalizeWhiteSpace: () => normalizeWhiteSpace,
|
||||
parseRegex: () => parseRegex,
|
||||
quoteCSSAttributeValue: () => quoteCSSAttributeValue,
|
||||
stripAnsiEscapes: () => stripAnsiEscapes,
|
||||
toSnakeCase: () => toSnakeCase,
|
||||
toTitleCase: () => toTitleCase,
|
||||
trimString: () => trimString,
|
||||
@@ -60,6 +65,31 @@ function toTitleCase(name) {
|
||||
function toSnakeCase(name) {
|
||||
return name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z])([A-Z][a-z])/g, "$1_$2").toLowerCase();
|
||||
}
|
||||
function formatObject(value, indent = " ", mode = "multiline") {
|
||||
if (typeof value === "string")
|
||||
return escapeWithQuotes(value, "'");
|
||||
if (Array.isArray(value))
|
||||
return `[${value.map((o) => formatObject(o)).join(", ")}]`;
|
||||
if (typeof value === "object") {
|
||||
const keys = Object.keys(value).filter((key) => value[key] !== void 0).sort();
|
||||
if (!keys.length)
|
||||
return "{}";
|
||||
const tokens = [];
|
||||
for (const key of keys)
|
||||
tokens.push(`${key}: ${formatObject(value[key])}`);
|
||||
if (mode === "multiline")
|
||||
return `{
|
||||
${tokens.join(`,
|
||||
${indent}`)}
|
||||
}`;
|
||||
return `{ ${tokens.join(", ")} }`;
|
||||
}
|
||||
return String(value);
|
||||
}
|
||||
function formatObjectOrVoid(value, indent = " ") {
|
||||
const result = formatObject(value, indent);
|
||||
return result === "{}" ? "" : result;
|
||||
}
|
||||
function quoteCSSAttributeValue(text) {
|
||||
return `"${text.replace(/["\\]/g, (char) => "\\" + char)}"`;
|
||||
}
|
||||
@@ -133,8 +163,23 @@ function longestCommonSubstring(s1, s2) {
|
||||
}
|
||||
return s1.slice(endingIndex - maxLen, endingIndex);
|
||||
}
|
||||
function parseRegex(regex) {
|
||||
if (regex[0] !== "/")
|
||||
throw new Error(`Invalid regex, must start with '/': ${regex}`);
|
||||
const lastSlash = regex.lastIndexOf("/");
|
||||
if (lastSlash <= 0)
|
||||
throw new Error(`Invalid regex, must end with '/' followed by optional flags: ${regex}`);
|
||||
const source = regex.slice(1, lastSlash);
|
||||
const flags = regex.slice(lastSlash + 1);
|
||||
return new RegExp(source, flags);
|
||||
}
|
||||
const ansiRegex = new RegExp("([\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~])))", "g");
|
||||
function stripAnsiEscapes(str) {
|
||||
return str.replace(ansiRegex, "");
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
ansiRegex,
|
||||
cacheNormalizedWhitespaces,
|
||||
escapeForAttributeSelector,
|
||||
escapeForTextSelector,
|
||||
@@ -143,11 +188,15 @@ function longestCommonSubstring(s1, s2) {
|
||||
escapeRegExp,
|
||||
escapeTemplateString,
|
||||
escapeWithQuotes,
|
||||
formatObject,
|
||||
formatObjectOrVoid,
|
||||
isString,
|
||||
longestCommonSubstring,
|
||||
normalizeEscapedRegexQuotes,
|
||||
normalizeWhiteSpace,
|
||||
parseRegex,
|
||||
quoteCSSAttributeValue,
|
||||
stripAnsiEscapes,
|
||||
toSnakeCase,
|
||||
toTitleCase,
|
||||
trimString,
|
||||
|
||||
16
node_modules/playwright-core/lib/utils/isomorphic/trace/entries.js
generated
vendored
Normal file
16
node_modules/playwright-core/lib/utils/isomorphic/trace/entries.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var entries_exports = {};
|
||||
module.exports = __toCommonJS(entries_exports);
|
||||
499
node_modules/playwright-core/lib/utils/isomorphic/trace/snapshotRenderer.js
generated
vendored
Normal file
499
node_modules/playwright-core/lib/utils/isomorphic/trace/snapshotRenderer.js
generated
vendored
Normal file
@@ -0,0 +1,499 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var snapshotRenderer_exports = {};
|
||||
__export(snapshotRenderer_exports, {
|
||||
SnapshotRenderer: () => SnapshotRenderer,
|
||||
rewriteURLForCustomProtocol: () => rewriteURLForCustomProtocol
|
||||
});
|
||||
module.exports = __toCommonJS(snapshotRenderer_exports);
|
||||
var import_stringUtils = require("../stringUtils");
|
||||
function findClosest(items, metric, target) {
|
||||
return items.find((item, index) => {
|
||||
if (index === items.length - 1)
|
||||
return true;
|
||||
const next = items[index + 1];
|
||||
return Math.abs(metric(item) - target) < Math.abs(metric(next) - target);
|
||||
});
|
||||
}
|
||||
function isNodeNameAttributesChildNodesSnapshot(n) {
|
||||
return Array.isArray(n) && typeof n[0] === "string";
|
||||
}
|
||||
function isSubtreeReferenceSnapshot(n) {
|
||||
return Array.isArray(n) && Array.isArray(n[0]);
|
||||
}
|
||||
class SnapshotRenderer {
|
||||
constructor(htmlCache, resources, snapshots, screencastFrames, index) {
|
||||
this._htmlCache = htmlCache;
|
||||
this._resources = resources;
|
||||
this._snapshots = snapshots;
|
||||
this._index = index;
|
||||
this._snapshot = snapshots[index];
|
||||
this._callId = snapshots[index].callId;
|
||||
this._screencastFrames = screencastFrames;
|
||||
this.snapshotName = snapshots[index].snapshotName;
|
||||
}
|
||||
snapshot() {
|
||||
return this._snapshots[this._index];
|
||||
}
|
||||
viewport() {
|
||||
return this._snapshots[this._index].viewport;
|
||||
}
|
||||
closestScreenshot() {
|
||||
const { wallTime, timestamp } = this.snapshot();
|
||||
const closestFrame = wallTime && this._screencastFrames[0]?.frameSwapWallTime ? findClosest(this._screencastFrames, (frame) => frame.frameSwapWallTime, wallTime) : findClosest(this._screencastFrames, (frame) => frame.timestamp, timestamp);
|
||||
return closestFrame?.sha1;
|
||||
}
|
||||
render() {
|
||||
const result = [];
|
||||
const visit = (n, snapshotIndex, parentTag, parentAttrs) => {
|
||||
if (typeof n === "string") {
|
||||
if (parentTag === "STYLE" || parentTag === "style")
|
||||
result.push(escapeURLsInStyleSheet(rewriteURLsInStyleSheetForCustomProtocol(n)));
|
||||
else
|
||||
result.push((0, import_stringUtils.escapeHTML)(n));
|
||||
return;
|
||||
}
|
||||
if (isSubtreeReferenceSnapshot(n)) {
|
||||
const referenceIndex = snapshotIndex - n[0][0];
|
||||
if (referenceIndex >= 0 && referenceIndex <= snapshotIndex) {
|
||||
const nodes = snapshotNodes(this._snapshots[referenceIndex]);
|
||||
const nodeIndex = n[0][1];
|
||||
if (nodeIndex >= 0 && nodeIndex < nodes.length)
|
||||
return visit(nodes[nodeIndex], referenceIndex, parentTag, parentAttrs);
|
||||
}
|
||||
} else if (isNodeNameAttributesChildNodesSnapshot(n)) {
|
||||
const [name, nodeAttrs, ...children] = n;
|
||||
const nodeName = name === "NOSCRIPT" ? "X-NOSCRIPT" : name;
|
||||
const attrs = Object.entries(nodeAttrs || {});
|
||||
result.push("<", nodeName);
|
||||
const kCurrentSrcAttribute = "__playwright_current_src__";
|
||||
const isFrame = nodeName === "IFRAME" || nodeName === "FRAME";
|
||||
const isAnchor = nodeName === "A";
|
||||
const isImg = nodeName === "IMG";
|
||||
const isImgWithCurrentSrc = isImg && attrs.some((a) => a[0] === kCurrentSrcAttribute);
|
||||
const isSourceInsidePictureWithCurrentSrc = nodeName === "SOURCE" && parentTag === "PICTURE" && parentAttrs?.some((a) => a[0] === kCurrentSrcAttribute);
|
||||
for (const [attr, value] of attrs) {
|
||||
let attrName = attr;
|
||||
if (isFrame && attr.toLowerCase() === "src") {
|
||||
attrName = "__playwright_src__";
|
||||
}
|
||||
if (isImg && attr === kCurrentSrcAttribute) {
|
||||
attrName = "src";
|
||||
}
|
||||
if (["src", "srcset"].includes(attr.toLowerCase()) && (isImgWithCurrentSrc || isSourceInsidePictureWithCurrentSrc)) {
|
||||
attrName = "_" + attrName;
|
||||
}
|
||||
let attrValue = value;
|
||||
if (!isAnchor && (attr.toLowerCase() === "href" || attr.toLowerCase() === "src" || attr === kCurrentSrcAttribute))
|
||||
attrValue = rewriteURLForCustomProtocol(value);
|
||||
result.push(" ", attrName, '="', (0, import_stringUtils.escapeHTMLAttribute)(attrValue), '"');
|
||||
}
|
||||
result.push(">");
|
||||
for (const child of children)
|
||||
visit(child, snapshotIndex, nodeName, attrs);
|
||||
if (!autoClosing.has(nodeName))
|
||||
result.push("</", nodeName, ">");
|
||||
return;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
};
|
||||
const snapshot = this._snapshot;
|
||||
const html = this._htmlCache.getOrCompute(this, () => {
|
||||
visit(snapshot.html, this._index, void 0, void 0);
|
||||
const prefix = snapshot.doctype ? `<!DOCTYPE ${snapshot.doctype}>` : "";
|
||||
const html2 = prefix + [
|
||||
// Hide the document in order to prevent flickering. We will unhide once script has processed shadow.
|
||||
"<style>*,*::before,*::after { visibility: hidden }</style>",
|
||||
`<script>${snapshotScript(this.viewport(), this._callId, this.snapshotName)}</script>`
|
||||
].join("") + result.join("");
|
||||
return { value: html2, size: html2.length };
|
||||
});
|
||||
return { html, pageId: snapshot.pageId, frameId: snapshot.frameId, index: this._index };
|
||||
}
|
||||
resourceByUrl(url, method) {
|
||||
const snapshot = this._snapshot;
|
||||
let sameFrameResource;
|
||||
let otherFrameResource;
|
||||
for (const resource of this._resources) {
|
||||
if (typeof resource._monotonicTime === "number" && resource._monotonicTime >= snapshot.timestamp)
|
||||
break;
|
||||
if (resource.response.status === 304) {
|
||||
continue;
|
||||
}
|
||||
if (resource.request.url === url && resource.request.method === method) {
|
||||
if (resource._frameref === snapshot.frameId)
|
||||
sameFrameResource = resource;
|
||||
else
|
||||
otherFrameResource = resource;
|
||||
}
|
||||
}
|
||||
let result = sameFrameResource ?? otherFrameResource;
|
||||
if (result && method.toUpperCase() === "GET") {
|
||||
let override = snapshot.resourceOverrides.find((o) => o.url === url);
|
||||
if (override?.ref) {
|
||||
const index = this._index - override.ref;
|
||||
if (index >= 0 && index < this._snapshots.length)
|
||||
override = this._snapshots[index].resourceOverrides.find((o) => o.url === url);
|
||||
}
|
||||
if (override?.sha1) {
|
||||
result = {
|
||||
...result,
|
||||
response: {
|
||||
...result.response,
|
||||
content: {
|
||||
...result.response.content,
|
||||
_sha1: override.sha1
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
const autoClosing = /* @__PURE__ */ new Set(["AREA", "BASE", "BR", "COL", "COMMAND", "EMBED", "HR", "IMG", "INPUT", "KEYGEN", "LINK", "MENUITEM", "META", "PARAM", "SOURCE", "TRACK", "WBR"]);
|
||||
function snapshotNodes(snapshot) {
|
||||
if (!snapshot._nodes) {
|
||||
const nodes = [];
|
||||
const visit = (n) => {
|
||||
if (typeof n === "string") {
|
||||
nodes.push(n);
|
||||
} else if (isNodeNameAttributesChildNodesSnapshot(n)) {
|
||||
const [, , ...children] = n;
|
||||
for (const child of children)
|
||||
visit(child);
|
||||
nodes.push(n);
|
||||
}
|
||||
};
|
||||
visit(snapshot.html);
|
||||
snapshot._nodes = nodes;
|
||||
}
|
||||
return snapshot._nodes;
|
||||
}
|
||||
function snapshotScript(viewport, ...targetIds) {
|
||||
function applyPlaywrightAttributes(viewport2, ...targetIds2) {
|
||||
const win = window;
|
||||
const searchParams = new URLSearchParams(win.location.search);
|
||||
const shouldPopulateCanvasFromScreenshot = searchParams.has("shouldPopulateCanvasFromScreenshot");
|
||||
const isUnderTest = searchParams.has("isUnderTest");
|
||||
const frameBoundingRectsInfo = {
|
||||
viewport: viewport2,
|
||||
frames: /* @__PURE__ */ new WeakMap()
|
||||
};
|
||||
win["__playwright_frame_bounding_rects__"] = frameBoundingRectsInfo;
|
||||
const kPointerWarningTitle = "Recorded click position in absolute coordinates did not match the center of the clicked element. This is likely due to a difference between the test runner and the trace viewer operating systems.";
|
||||
const scrollTops = [];
|
||||
const scrollLefts = [];
|
||||
const targetElements = [];
|
||||
const canvasElements = [];
|
||||
let topSnapshotWindow = win;
|
||||
while (topSnapshotWindow !== topSnapshotWindow.parent && !topSnapshotWindow.location.pathname.match(/\/page@[a-z0-9]+$/))
|
||||
topSnapshotWindow = topSnapshotWindow.parent;
|
||||
const visit = (root) => {
|
||||
for (const e of root.querySelectorAll(`[__playwright_scroll_top_]`))
|
||||
scrollTops.push(e);
|
||||
for (const e of root.querySelectorAll(`[__playwright_scroll_left_]`))
|
||||
scrollLefts.push(e);
|
||||
for (const element of root.querySelectorAll(`[__playwright_value_]`)) {
|
||||
const inputElement = element;
|
||||
if (inputElement.type !== "file")
|
||||
inputElement.value = inputElement.getAttribute("__playwright_value_");
|
||||
element.removeAttribute("__playwright_value_");
|
||||
}
|
||||
for (const element of root.querySelectorAll(`[__playwright_checked_]`)) {
|
||||
element.checked = element.getAttribute("__playwright_checked_") === "true";
|
||||
element.removeAttribute("__playwright_checked_");
|
||||
}
|
||||
for (const element of root.querySelectorAll(`[__playwright_selected_]`)) {
|
||||
element.selected = element.getAttribute("__playwright_selected_") === "true";
|
||||
element.removeAttribute("__playwright_selected_");
|
||||
}
|
||||
for (const element of root.querySelectorAll(`[__playwright_popover_open_]`)) {
|
||||
try {
|
||||
element.showPopover();
|
||||
} catch {
|
||||
}
|
||||
element.removeAttribute("__playwright_popover_open_");
|
||||
}
|
||||
for (const element of root.querySelectorAll(`[__playwright_dialog_open_]`)) {
|
||||
try {
|
||||
if (element.getAttribute("__playwright_dialog_open_") === "modal")
|
||||
element.showModal();
|
||||
else
|
||||
element.show();
|
||||
} catch {
|
||||
}
|
||||
element.removeAttribute("__playwright_dialog_open_");
|
||||
}
|
||||
for (const targetId of targetIds2) {
|
||||
for (const target of root.querySelectorAll(`[__playwright_target__="${targetId}"]`)) {
|
||||
const style = target.style;
|
||||
style.outline = "2px solid #006ab1";
|
||||
style.backgroundColor = "#6fa8dc7f";
|
||||
targetElements.push(target);
|
||||
}
|
||||
}
|
||||
for (const iframe of root.querySelectorAll("iframe, frame")) {
|
||||
const boundingRectJson = iframe.getAttribute("__playwright_bounding_rect__");
|
||||
iframe.removeAttribute("__playwright_bounding_rect__");
|
||||
const boundingRect = boundingRectJson ? JSON.parse(boundingRectJson) : void 0;
|
||||
if (boundingRect)
|
||||
frameBoundingRectsInfo.frames.set(iframe, { boundingRect, scrollLeft: 0, scrollTop: 0 });
|
||||
const src = iframe.getAttribute("__playwright_src__");
|
||||
if (!src) {
|
||||
iframe.setAttribute("src", 'data:text/html,<body style="background: #ddd"></body>');
|
||||
} else {
|
||||
const url = new URL(win.location.href);
|
||||
const index = url.pathname.lastIndexOf("/snapshot/");
|
||||
if (index !== -1)
|
||||
url.pathname = url.pathname.substring(0, index + 1);
|
||||
url.pathname += src.substring(1);
|
||||
iframe.setAttribute("src", url.toString());
|
||||
}
|
||||
}
|
||||
{
|
||||
const body = root.querySelector(`body[__playwright_custom_elements__]`);
|
||||
if (body && win.customElements) {
|
||||
const customElements = (body.getAttribute("__playwright_custom_elements__") || "").split(",");
|
||||
for (const elementName of customElements)
|
||||
win.customElements.define(elementName, class extends HTMLElement {
|
||||
});
|
||||
}
|
||||
}
|
||||
for (const element of root.querySelectorAll(`template[__playwright_shadow_root_]`)) {
|
||||
const template = element;
|
||||
const shadowRoot = template.parentElement.attachShadow({ mode: "open" });
|
||||
shadowRoot.appendChild(template.content);
|
||||
template.remove();
|
||||
visit(shadowRoot);
|
||||
}
|
||||
for (const element of root.querySelectorAll("a"))
|
||||
element.addEventListener("click", (event) => {
|
||||
event.preventDefault();
|
||||
});
|
||||
if ("adoptedStyleSheets" in root) {
|
||||
const adoptedSheets = [...root.adoptedStyleSheets];
|
||||
for (const element of root.querySelectorAll(`template[__playwright_style_sheet_]`)) {
|
||||
const template = element;
|
||||
const sheet = new CSSStyleSheet();
|
||||
sheet.replaceSync(template.getAttribute("__playwright_style_sheet_"));
|
||||
adoptedSheets.push(sheet);
|
||||
}
|
||||
root.adoptedStyleSheets = adoptedSheets;
|
||||
}
|
||||
canvasElements.push(...root.querySelectorAll("canvas"));
|
||||
};
|
||||
const onLoad = () => {
|
||||
win.removeEventListener("load", onLoad);
|
||||
for (const element of scrollTops) {
|
||||
element.scrollTop = +element.getAttribute("__playwright_scroll_top_");
|
||||
element.removeAttribute("__playwright_scroll_top_");
|
||||
if (frameBoundingRectsInfo.frames.has(element))
|
||||
frameBoundingRectsInfo.frames.get(element).scrollTop = element.scrollTop;
|
||||
}
|
||||
for (const element of scrollLefts) {
|
||||
element.scrollLeft = +element.getAttribute("__playwright_scroll_left_");
|
||||
element.removeAttribute("__playwright_scroll_left_");
|
||||
if (frameBoundingRectsInfo.frames.has(element))
|
||||
frameBoundingRectsInfo.frames.get(element).scrollLeft = element.scrollLeft;
|
||||
}
|
||||
win.document.styleSheets[0].disabled = true;
|
||||
const search = new URL(win.location.href).searchParams;
|
||||
const isTopFrame = win === topSnapshotWindow;
|
||||
if (search.get("pointX") && search.get("pointY")) {
|
||||
const pointX = +search.get("pointX");
|
||||
const pointY = +search.get("pointY");
|
||||
const hasInputTarget = search.has("hasInputTarget");
|
||||
const hasTargetElements = targetElements.length > 0;
|
||||
const roots = win.document.documentElement ? [win.document.documentElement] : [];
|
||||
for (const target of hasTargetElements ? targetElements : roots) {
|
||||
const pointElement = win.document.createElement("x-pw-pointer");
|
||||
pointElement.style.position = "fixed";
|
||||
pointElement.style.backgroundColor = "#f44336";
|
||||
pointElement.style.width = "20px";
|
||||
pointElement.style.height = "20px";
|
||||
pointElement.style.borderRadius = "10px";
|
||||
pointElement.style.margin = "-10px 0 0 -10px";
|
||||
pointElement.style.zIndex = "2147483646";
|
||||
pointElement.style.display = "flex";
|
||||
pointElement.style.alignItems = "center";
|
||||
pointElement.style.justifyContent = "center";
|
||||
if (hasTargetElements) {
|
||||
const box = target.getBoundingClientRect();
|
||||
const centerX = box.left + box.width / 2;
|
||||
const centerY = box.top + box.height / 2;
|
||||
pointElement.style.left = centerX + "px";
|
||||
pointElement.style.top = centerY + "px";
|
||||
if (isTopFrame && (Math.abs(centerX - pointX) >= 10 || Math.abs(centerY - pointY) >= 10)) {
|
||||
const warningElement = win.document.createElement("x-pw-pointer-warning");
|
||||
warningElement.textContent = "\u26A0";
|
||||
warningElement.style.fontSize = "19px";
|
||||
warningElement.style.color = "white";
|
||||
warningElement.style.marginTop = "-3.5px";
|
||||
warningElement.style.userSelect = "none";
|
||||
pointElement.appendChild(warningElement);
|
||||
pointElement.setAttribute("title", kPointerWarningTitle);
|
||||
}
|
||||
win.document.documentElement.appendChild(pointElement);
|
||||
} else if (isTopFrame && !hasInputTarget) {
|
||||
pointElement.style.left = pointX + "px";
|
||||
pointElement.style.top = pointY + "px";
|
||||
win.document.documentElement.appendChild(pointElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (canvasElements.length > 0) {
|
||||
let drawCheckerboard2 = function(context, canvas) {
|
||||
function createCheckerboardPattern() {
|
||||
const pattern = win.document.createElement("canvas");
|
||||
pattern.width = pattern.width / Math.floor(pattern.width / 24);
|
||||
pattern.height = pattern.height / Math.floor(pattern.height / 24);
|
||||
const context2 = pattern.getContext("2d");
|
||||
context2.fillStyle = "lightgray";
|
||||
context2.fillRect(0, 0, pattern.width, pattern.height);
|
||||
context2.fillStyle = "white";
|
||||
context2.fillRect(0, 0, pattern.width / 2, pattern.height / 2);
|
||||
context2.fillRect(pattern.width / 2, pattern.height / 2, pattern.width, pattern.height);
|
||||
return context2.createPattern(pattern, "repeat");
|
||||
}
|
||||
context.fillStyle = createCheckerboardPattern();
|
||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
};
|
||||
var drawCheckerboard = drawCheckerboard2;
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
for (const canvas of canvasElements) {
|
||||
const context = canvas.getContext("2d");
|
||||
const boundingRectAttribute = canvas.getAttribute("__playwright_bounding_rect__");
|
||||
canvas.removeAttribute("__playwright_bounding_rect__");
|
||||
if (!boundingRectAttribute)
|
||||
continue;
|
||||
let boundingRect;
|
||||
try {
|
||||
boundingRect = JSON.parse(boundingRectAttribute);
|
||||
} catch (e) {
|
||||
continue;
|
||||
}
|
||||
let currWindow = win;
|
||||
while (currWindow !== topSnapshotWindow) {
|
||||
const iframe = currWindow.frameElement;
|
||||
currWindow = currWindow.parent;
|
||||
const iframeInfo = currWindow["__playwright_frame_bounding_rects__"]?.frames.get(iframe);
|
||||
if (!iframeInfo?.boundingRect)
|
||||
break;
|
||||
const leftOffset = iframeInfo.boundingRect.left - iframeInfo.scrollLeft;
|
||||
const topOffset = iframeInfo.boundingRect.top - iframeInfo.scrollTop;
|
||||
boundingRect.left += leftOffset;
|
||||
boundingRect.top += topOffset;
|
||||
boundingRect.right += leftOffset;
|
||||
boundingRect.bottom += topOffset;
|
||||
}
|
||||
const { width, height } = topSnapshotWindow["__playwright_frame_bounding_rects__"].viewport;
|
||||
boundingRect.left = boundingRect.left / width;
|
||||
boundingRect.top = boundingRect.top / height;
|
||||
boundingRect.right = boundingRect.right / width;
|
||||
boundingRect.bottom = boundingRect.bottom / height;
|
||||
const partiallyUncaptured = boundingRect.right > 1 || boundingRect.bottom > 1;
|
||||
const fullyUncaptured = boundingRect.left > 1 || boundingRect.top > 1;
|
||||
if (fullyUncaptured) {
|
||||
canvas.title = `Playwright couldn't capture canvas contents because it's located outside the viewport.`;
|
||||
continue;
|
||||
}
|
||||
drawCheckerboard2(context, canvas);
|
||||
if (shouldPopulateCanvasFromScreenshot) {
|
||||
context.drawImage(img, boundingRect.left * img.width, boundingRect.top * img.height, (boundingRect.right - boundingRect.left) * img.width, (boundingRect.bottom - boundingRect.top) * img.height, 0, 0, canvas.width, canvas.height);
|
||||
if (partiallyUncaptured)
|
||||
canvas.title = `Playwright couldn't capture full canvas contents because it's located partially outside the viewport.`;
|
||||
else
|
||||
canvas.title = `Canvas contents are displayed on a best-effort basis based on viewport screenshots taken during test execution.`;
|
||||
} else {
|
||||
canvas.title = "Canvas content display is disabled.";
|
||||
}
|
||||
if (isUnderTest)
|
||||
console.log(`canvas drawn:`, JSON.stringify([boundingRect.left, boundingRect.top, boundingRect.right - boundingRect.left, boundingRect.bottom - boundingRect.top].map((v) => Math.floor(v * 100))));
|
||||
}
|
||||
};
|
||||
img.onerror = () => {
|
||||
for (const canvas of canvasElements) {
|
||||
const context = canvas.getContext("2d");
|
||||
drawCheckerboard2(context, canvas);
|
||||
canvas.title = `Playwright couldn't show canvas contents because the screenshot failed to load.`;
|
||||
}
|
||||
};
|
||||
img.src = location.href.replace("/snapshot", "/closest-screenshot");
|
||||
}
|
||||
};
|
||||
const onDOMContentLoaded = () => visit(win.document);
|
||||
win.addEventListener("load", onLoad);
|
||||
win.addEventListener("DOMContentLoaded", onDOMContentLoaded);
|
||||
}
|
||||
return `
|
||||
(${applyPlaywrightAttributes.toString()})(${JSON.stringify(viewport)}${targetIds.map((id) => `, "${id}"`).join("")})`;
|
||||
}
|
||||
const schemas = ["about:", "blob:", "data:", "file:", "ftp:", "http:", "https:", "mailto:", "sftp:", "ws:", "wss:"];
|
||||
const kLegacyBlobPrefix = "http://playwright.bloburl/#";
|
||||
function rewriteURLForCustomProtocol(href) {
|
||||
if (href.startsWith(kLegacyBlobPrefix))
|
||||
href = href.substring(kLegacyBlobPrefix.length);
|
||||
try {
|
||||
const url = new URL(href);
|
||||
if (url.protocol === "javascript:" || url.protocol === "vbscript:")
|
||||
return "javascript:void(0)";
|
||||
const isBlob = url.protocol === "blob:";
|
||||
const isFile = url.protocol === "file:";
|
||||
if (!isBlob && !isFile && schemas.includes(url.protocol))
|
||||
return href;
|
||||
const prefix = "pw-" + url.protocol.slice(0, url.protocol.length - 1);
|
||||
if (!isFile)
|
||||
url.protocol = "https:";
|
||||
url.hostname = url.hostname ? `${prefix}--${url.hostname}` : prefix;
|
||||
if (isFile) {
|
||||
url.protocol = "https:";
|
||||
}
|
||||
return url.toString();
|
||||
} catch {
|
||||
return href;
|
||||
}
|
||||
}
|
||||
const urlInCSSRegex = /url\(['"]?([\w-]+:)\/\//ig;
|
||||
function rewriteURLsInStyleSheetForCustomProtocol(text) {
|
||||
return text.replace(urlInCSSRegex, (match, protocol) => {
|
||||
const isBlob = protocol === "blob:";
|
||||
const isFile = protocol === "file:";
|
||||
if (!isBlob && !isFile && schemas.includes(protocol))
|
||||
return match;
|
||||
return match.replace(protocol + "//", `https://pw-${protocol.slice(0, -1)}--`);
|
||||
});
|
||||
}
|
||||
const urlToEscapeRegex1 = /url\(\s*'([^']*)'\s*\)/ig;
|
||||
const urlToEscapeRegex2 = /url\(\s*"([^"]*)"\s*\)/ig;
|
||||
function escapeURLsInStyleSheet(text) {
|
||||
const replacer = (match, url) => {
|
||||
if (url.includes("</"))
|
||||
return match.replace(url, encodeURI(url));
|
||||
return match;
|
||||
};
|
||||
return text.replace(urlToEscapeRegex1, replacer).replace(urlToEscapeRegex2, replacer);
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
SnapshotRenderer,
|
||||
rewriteURLForCustomProtocol
|
||||
});
|
||||
120
node_modules/playwright-core/lib/utils/isomorphic/trace/snapshotServer.js
generated
vendored
Normal file
120
node_modules/playwright-core/lib/utils/isomorphic/trace/snapshotServer.js
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var snapshotServer_exports = {};
|
||||
__export(snapshotServer_exports, {
|
||||
SnapshotServer: () => SnapshotServer
|
||||
});
|
||||
module.exports = __toCommonJS(snapshotServer_exports);
|
||||
class SnapshotServer {
|
||||
constructor(snapshotStorage, resourceLoader) {
|
||||
this._snapshotIds = /* @__PURE__ */ new Map();
|
||||
this._snapshotStorage = snapshotStorage;
|
||||
this._resourceLoader = resourceLoader;
|
||||
}
|
||||
serveSnapshot(pageOrFrameId, searchParams, snapshotUrl) {
|
||||
const snapshot = this._snapshot(pageOrFrameId, searchParams);
|
||||
if (!snapshot)
|
||||
return new Response(null, { status: 404 });
|
||||
const renderedSnapshot = snapshot.render();
|
||||
this._snapshotIds.set(snapshotUrl, snapshot);
|
||||
return new Response(renderedSnapshot.html, { status: 200, headers: { "Content-Type": "text/html; charset=utf-8" } });
|
||||
}
|
||||
async serveClosestScreenshot(pageOrFrameId, searchParams) {
|
||||
const snapshot = this._snapshot(pageOrFrameId, searchParams);
|
||||
const sha1 = snapshot?.closestScreenshot();
|
||||
if (!sha1)
|
||||
return new Response(null, { status: 404 });
|
||||
return new Response(await this._resourceLoader(sha1));
|
||||
}
|
||||
serveSnapshotInfo(pageOrFrameId, searchParams) {
|
||||
const snapshot = this._snapshot(pageOrFrameId, searchParams);
|
||||
return this._respondWithJson(snapshot ? {
|
||||
viewport: snapshot.viewport(),
|
||||
url: snapshot.snapshot().frameUrl,
|
||||
timestamp: snapshot.snapshot().timestamp,
|
||||
wallTime: snapshot.snapshot().wallTime
|
||||
} : {
|
||||
error: "No snapshot found"
|
||||
});
|
||||
}
|
||||
_snapshot(pageOrFrameId, params) {
|
||||
const name = params.get("name");
|
||||
return this._snapshotStorage.snapshotByName(pageOrFrameId, name);
|
||||
}
|
||||
_respondWithJson(object) {
|
||||
return new Response(JSON.stringify(object), {
|
||||
status: 200,
|
||||
headers: {
|
||||
"Cache-Control": "public, max-age=31536000",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
});
|
||||
}
|
||||
async serveResource(requestUrlAlternatives, method, snapshotUrl) {
|
||||
let resource;
|
||||
const snapshot = this._snapshotIds.get(snapshotUrl);
|
||||
for (const requestUrl of requestUrlAlternatives) {
|
||||
resource = snapshot?.resourceByUrl(removeHash(requestUrl), method);
|
||||
if (resource)
|
||||
break;
|
||||
}
|
||||
if (!resource)
|
||||
return new Response(null, { status: 404 });
|
||||
const sha1 = resource.response.content._sha1;
|
||||
const content = sha1 ? await this._resourceLoader(sha1) || new Blob([]) : new Blob([]);
|
||||
let contentType = resource.response.content.mimeType;
|
||||
const isTextEncoding = /^text\/|^application\/(javascript|json)/.test(contentType);
|
||||
if (isTextEncoding && !contentType.includes("charset"))
|
||||
contentType = `${contentType}; charset=utf-8`;
|
||||
const headers = new Headers();
|
||||
if (contentType !== "x-unknown")
|
||||
headers.set("Content-Type", contentType);
|
||||
for (const { name, value } of resource.response.headers)
|
||||
headers.set(name, value);
|
||||
headers.delete("Content-Encoding");
|
||||
headers.delete("Access-Control-Allow-Origin");
|
||||
headers.set("Access-Control-Allow-Origin", "*");
|
||||
headers.delete("Content-Length");
|
||||
headers.set("Content-Length", String(content.size));
|
||||
if (this._snapshotStorage.hasResourceOverride(resource.request.url))
|
||||
headers.set("Cache-Control", "no-store, no-cache, max-age=0");
|
||||
else
|
||||
headers.set("Cache-Control", "public, max-age=31536000");
|
||||
const { status } = resource.response;
|
||||
const isNullBodyStatus = status === 101 || status === 204 || status === 205 || status === 304;
|
||||
return new Response(isNullBodyStatus ? null : content, {
|
||||
headers,
|
||||
status: resource.response.status,
|
||||
statusText: resource.response.statusText
|
||||
});
|
||||
}
|
||||
}
|
||||
function removeHash(url) {
|
||||
try {
|
||||
const u = new URL(url);
|
||||
u.hash = "";
|
||||
return u.toString();
|
||||
} catch (e) {
|
||||
return url;
|
||||
}
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
SnapshotServer
|
||||
});
|
||||
89
node_modules/playwright-core/lib/utils/isomorphic/trace/snapshotStorage.js
generated
vendored
Normal file
89
node_modules/playwright-core/lib/utils/isomorphic/trace/snapshotStorage.js
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var snapshotStorage_exports = {};
|
||||
__export(snapshotStorage_exports, {
|
||||
SnapshotStorage: () => SnapshotStorage
|
||||
});
|
||||
module.exports = __toCommonJS(snapshotStorage_exports);
|
||||
var import_snapshotRenderer = require("./snapshotRenderer");
|
||||
var import_lruCache = require("../lruCache");
|
||||
class SnapshotStorage {
|
||||
constructor() {
|
||||
this._frameSnapshots = /* @__PURE__ */ new Map();
|
||||
this._cache = new import_lruCache.LRUCache(1e8);
|
||||
// 100MB per each trace
|
||||
this._contextToResources = /* @__PURE__ */ new Map();
|
||||
this._resourceUrlsWithOverrides = /* @__PURE__ */ new Set();
|
||||
}
|
||||
addResource(contextId, resource) {
|
||||
resource.request.url = (0, import_snapshotRenderer.rewriteURLForCustomProtocol)(resource.request.url);
|
||||
this._ensureResourcesForContext(contextId).push(resource);
|
||||
}
|
||||
addFrameSnapshot(contextId, snapshot, screencastFrames) {
|
||||
for (const override of snapshot.resourceOverrides)
|
||||
override.url = (0, import_snapshotRenderer.rewriteURLForCustomProtocol)(override.url);
|
||||
let frameSnapshots = this._frameSnapshots.get(snapshot.frameId);
|
||||
if (!frameSnapshots) {
|
||||
frameSnapshots = {
|
||||
raw: [],
|
||||
renderers: []
|
||||
};
|
||||
this._frameSnapshots.set(snapshot.frameId, frameSnapshots);
|
||||
if (snapshot.isMainFrame)
|
||||
this._frameSnapshots.set(snapshot.pageId, frameSnapshots);
|
||||
}
|
||||
frameSnapshots.raw.push(snapshot);
|
||||
const resources = this._ensureResourcesForContext(contextId);
|
||||
const renderer = new import_snapshotRenderer.SnapshotRenderer(this._cache, resources, frameSnapshots.raw, screencastFrames, frameSnapshots.raw.length - 1);
|
||||
frameSnapshots.renderers.push(renderer);
|
||||
return renderer;
|
||||
}
|
||||
snapshotByName(pageOrFrameId, snapshotName) {
|
||||
const snapshot = this._frameSnapshots.get(pageOrFrameId);
|
||||
return snapshot?.renderers.find((r) => r.snapshotName === snapshotName);
|
||||
}
|
||||
snapshotsForTest() {
|
||||
return [...this._frameSnapshots.keys()];
|
||||
}
|
||||
finalize() {
|
||||
for (const resources of this._contextToResources.values())
|
||||
resources.sort((a, b) => (a._monotonicTime || 0) - (b._monotonicTime || 0));
|
||||
for (const frameSnapshots of this._frameSnapshots.values()) {
|
||||
for (const snapshot of frameSnapshots.raw) {
|
||||
for (const override of snapshot.resourceOverrides)
|
||||
this._resourceUrlsWithOverrides.add(override.url);
|
||||
}
|
||||
}
|
||||
}
|
||||
hasResourceOverride(url) {
|
||||
return this._resourceUrlsWithOverrides.has(url);
|
||||
}
|
||||
_ensureResourcesForContext(contextId) {
|
||||
let resources = this._contextToResources.get(contextId);
|
||||
if (!resources) {
|
||||
resources = [];
|
||||
this._contextToResources.set(contextId, resources);
|
||||
}
|
||||
return resources;
|
||||
}
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
SnapshotStorage
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user