First Commit

This commit is contained in:
2025-08-28 19:35:28 -07:00
commit 264e65006a
488 changed files with 155661 additions and 0 deletions

View File

@@ -0,0 +1,446 @@
"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 bidiBrowser_exports = {};
__export(bidiBrowser_exports, {
BidiBrowser: () => BidiBrowser,
BidiBrowserContext: () => BidiBrowserContext,
Network: () => Network
});
module.exports = __toCommonJS(bidiBrowser_exports);
var import_eventsHelper = require("../utils/eventsHelper");
var import_browser = require("../browser");
var import_browserContext = require("../browserContext");
var network = __toESM(require("../network"));
var import_bidiConnection = require("./bidiConnection");
var import_bidiNetworkManager = require("./bidiNetworkManager");
var import_bidiPage = require("./bidiPage");
var import_page = require("../page");
var bidi = __toESM(require("./third_party/bidiProtocol"));
class BidiBrowser extends import_browser.Browser {
constructor(parent, transport, options) {
super(parent, options);
this._contexts = /* @__PURE__ */ new Map();
this._bidiPages = /* @__PURE__ */ new Map();
this._connection = new import_bidiConnection.BidiConnection(transport, this._onDisconnect.bind(this), options.protocolLogger, options.browserLogsCollector);
this._browserSession = this._connection.browserSession;
this._eventListeners = [
import_eventsHelper.eventsHelper.addEventListener(this._browserSession, "browsingContext.contextCreated", this._onBrowsingContextCreated.bind(this)),
import_eventsHelper.eventsHelper.addEventListener(this._browserSession, "script.realmDestroyed", this._onScriptRealmDestroyed.bind(this))
];
}
static async connect(parent, transport, options) {
const browser = new BidiBrowser(parent, transport, options);
if (options.__testHookOnConnectToBrowser)
await options.__testHookOnConnectToBrowser();
browser._bidiSessionInfo = await browser._browserSession.send("session.new", {
capabilities: {
alwaysMatch: {
acceptInsecureCerts: options.persistent?.internalIgnoreHTTPSErrors || options.persistent?.ignoreHTTPSErrors,
proxy: getProxyConfiguration(options.originalLaunchOptions.proxyOverride ?? options.proxy),
unhandledPromptBehavior: {
default: bidi.Session.UserPromptHandlerType.Ignore
},
webSocketUrl: true
}
}
});
await browser._browserSession.send("session.subscribe", {
events: [
"browsingContext",
"network",
"log",
"script"
]
});
if (options.persistent) {
const context = new BidiBrowserContext(browser, void 0, options.persistent);
browser._defaultContext = context;
await context._initialize();
const page = await browser._defaultContext.doCreateNewPage();
await page.waitForInitializedOrError();
}
return browser;
}
_onDisconnect() {
this._didClose();
}
async doCreateNewContext(options) {
const proxy = options.proxyOverride || options.proxy;
const { userContext } = await this._browserSession.send("browser.createUserContext", {
acceptInsecureCerts: options.internalIgnoreHTTPSErrors || options.ignoreHTTPSErrors,
proxy: getProxyConfiguration(proxy)
});
const context = new BidiBrowserContext(this, userContext, options);
await context._initialize();
this._contexts.set(userContext, context);
return context;
}
contexts() {
return Array.from(this._contexts.values());
}
version() {
return this._bidiSessionInfo.capabilities.browserVersion;
}
userAgent() {
return this._bidiSessionInfo.capabilities.userAgent;
}
isConnected() {
return !this._connection.isClosed();
}
_onBrowsingContextCreated(event) {
if (event.parent) {
const parentFrameId = event.parent;
for (const page2 of this._bidiPages.values()) {
const parentFrame = page2._page.frameManager.frame(parentFrameId);
if (!parentFrame)
continue;
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;
return;
}
return;
}
let context = this._contexts.get(event.userContext);
if (!context)
context = this._defaultContext;
if (!context)
return;
const session = this._connection.createMainFrameBrowsingContextSession(event.context);
const opener = event.originalOpener && this._bidiPages.get(event.originalOpener);
const page = new import_bidiPage.BidiPage(context, session, opener || null);
page._page.mainFrame()._url = event.url;
this._bidiPages.set(event.context, page);
}
_onBrowsingContextDestroyed(event) {
if (event.parent) {
this._browserSession.removeFrameBrowsingContext(event.context);
const parentFrameId = event.parent;
for (const page of this._bidiPages.values()) {
const parentFrame = page._page.frameManager.frame(parentFrameId);
if (!parentFrame)
continue;
page._page.frameManager.frameDetached(event.context);
return;
}
return;
}
const bidiPage = this._bidiPages.get(event.context);
if (!bidiPage)
return;
bidiPage.didClose();
this._bidiPages.delete(event.context);
}
_onScriptRealmDestroyed(event) {
for (const page of this._bidiPages.values()) {
if (page._onRealmDestroyed(event))
return;
}
}
}
class BidiBrowserContext extends import_browserContext.BrowserContext {
constructor(browser, browserContextId, options) {
super(browser, options, browserContextId);
this._originToPermissions = /* @__PURE__ */ new Map();
this._initScriptIds = /* @__PURE__ */ new Map();
this._authenticateProxyViaHeader();
}
_bidiPages() {
return [...this._browser._bidiPages.values()].filter((bidiPage) => bidiPage._browserContext === this);
}
async _initialize() {
const promises = [
super._initialize()
];
promises.push(this.doUpdateDefaultViewport());
if (this._options.geolocation)
promises.push(this.setGeolocation(this._options.geolocation));
if (this._options.locale) {
promises.push(this._browser._browserSession.send("emulation.setLocaleOverride", {
locale: this._options.locale,
userContexts: [this._userContextId()]
}));
}
await Promise.all(promises);
}
possiblyUninitializedPages() {
return this._bidiPages().map((bidiPage) => bidiPage._page);
}
async doCreateNewPage() {
const { context } = await this._browser._browserSession.send("browsingContext.create", {
type: bidi.BrowsingContext.CreateType.Window,
userContext: this._browserContextId
});
return this._browser._bidiPages.get(context)._page;
}
async doGetCookies(urls) {
const { cookies } = await this._browser._browserSession.send(
"storage.getCookies",
{ partition: { type: "storageKey", userContext: this._browserContextId } }
);
return network.filterCookies(cookies.map((c) => {
const copy = {
name: c.name,
value: (0, import_bidiNetworkManager.bidiBytesValueToString)(c.value),
domain: c.domain,
path: c.path,
httpOnly: c.httpOnly,
secure: c.secure,
expires: c.expiry ?? -1,
sameSite: c.sameSite ? fromBidiSameSite(c.sameSite) : "None"
};
return copy;
}), urls);
}
async addCookies(cookies) {
cookies = network.rewriteCookies(cookies);
const promises = cookies.map((c) => {
const cookie = {
name: c.name,
value: { type: "string", value: c.value },
domain: c.domain,
path: c.path,
httpOnly: c.httpOnly,
secure: c.secure,
sameSite: c.sameSite && toBidiSameSite(c.sameSite),
expiry: c.expires === -1 || c.expires === void 0 ? void 0 : Math.round(c.expires)
};
return this._browser._browserSession.send(
"storage.setCookie",
{ cookie, partition: { type: "storageKey", userContext: this._browserContextId } }
);
});
await Promise.all(promises);
}
async doClearCookies() {
await this._browser._browserSession.send(
"storage.deleteCookies",
{ partition: { type: "storageKey", userContext: this._browserContextId } }
);
}
async doGrantPermissions(origin, permissions) {
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)));
}
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)
)));
}
async _setPermission(origin, permission, state) {
await this._browser._browserSession.send("permissions.setPermission", {
descriptor: {
name: permission
},
state,
origin,
userContext: this._userContextId()
});
}
async setGeolocation(geolocation) {
(0, import_browserContext.verifyGeolocation)(geolocation);
this._options.geolocation = geolocation;
await this._browser._browserSession.send("emulation.setGeolocationOverride", {
coordinates: geolocation ? {
latitude: geolocation.latitude,
longitude: geolocation.longitude,
accuracy: geolocation.accuracy
} : null,
userContexts: [this._userContextId()]
});
}
async doUpdateExtraHTTPHeaders() {
}
async setUserAgent(userAgent) {
}
async doUpdateOffline() {
}
async doSetHTTPCredentials(httpCredentials) {
this._options.httpCredentials = httpCredentials;
for (const page of this.pages())
await page.delegate.updateHttpCredentials();
}
async doAddInitScript(initScript) {
const { script } = await this._browser._browserSession.send("script.addPreloadScript", {
// TODO: remove function call from the source.
functionDeclaration: `() => { return ${initScript.source} }`,
userContexts: [this._userContextId()]
});
this._initScriptIds.set(initScript, script);
}
async doRemoveInitScripts(initScripts) {
const ids = [];
for (const script of initScripts) {
const id = this._initScriptIds.get(script);
if (id)
ids.push(id);
this._initScriptIds.delete(script);
}
await Promise.all(ids.map((script) => this._browser._browserSession.send("script.removePreloadScript", { script })));
}
async doUpdateRequestInterception() {
}
async doUpdateDefaultViewport() {
if (!this._options.viewport)
return;
await this._browser._browserSession.send("browsingContext.setViewport", {
viewport: {
width: this._options.viewport.width,
height: this._options.viewport.height
},
devicePixelRatio: this._options.deviceScaleFactor || 1,
userContexts: [this._userContextId()]
});
}
async doUpdateDefaultEmulatedMedia() {
}
async doExposePlaywrightBinding() {
const args = [{
type: "channel",
value: {
channel: import_bidiPage.kPlaywrightBindingChannel,
ownership: bidi.Script.ResultOwnership.Root
}
}];
const functionDeclaration = `function addMainBinding(callback) { globalThis['${import_page.PageBinding.kBindingName}'] = callback; }`;
const promises = [];
promises.push(this._browser._browserSession.send("script.addPreloadScript", {
functionDeclaration,
arguments: args,
userContexts: [this._userContextId()]
}));
promises.push(...this._bidiPages().map((page) => {
const realms = [...page._realmToContext].filter(([realm, context]) => context.world === "main").map(([realm, context]) => realm);
return Promise.all(realms.map((realm) => {
return page._session.send("script.callFunction", {
functionDeclaration,
arguments: args,
target: { realm },
awaitPromise: false,
userActivation: false
});
}));
}));
await Promise.all(promises);
}
onClosePersistent() {
}
async clearCache() {
}
async doClose(reason) {
if (!this._browserContextId) {
await this._browser.close({ reason });
return;
}
await this._browser._browserSession.send("browser.removeUserContext", {
userContext: this._browserContextId
});
this._browser._contexts.delete(this._browserContextId);
}
async cancelDownload(uuid) {
}
_userContextId() {
if (this._browserContextId)
return this._browserContextId;
return "default";
}
}
function fromBidiSameSite(sameSite) {
switch (sameSite) {
case "strict":
return "Strict";
case "lax":
return "Lax";
case "none":
return "None";
}
return "None";
}
function toBidiSameSite(sameSite) {
switch (sameSite) {
case "Strict":
return bidi.Network.SameSite.Strict;
case "Lax":
return bidi.Network.SameSite.Lax;
case "None":
return bidi.Network.SameSite.None;
}
return bidi.Network.SameSite.None;
}
function getProxyConfiguration(proxySettings) {
if (!proxySettings)
return void 0;
const proxy = {
proxyType: "manual"
};
const url = new URL(proxySettings.server);
switch (url.protocol) {
case "http:":
proxy.httpProxy = url.host;
break;
case "https:":
proxy.sslProxy = url.host;
break;
case "socks4:":
proxy.socksProxy = url.host;
proxy.socksVersion = 4;
break;
case "socks5:":
proxy.socksProxy = url.host;
proxy.socksVersion = 5;
break;
default:
throw new Error("Invalid proxy server protocol: " + proxySettings.server);
}
const bypass = proxySettings.bypass ?? process.env.PLAYWRIGHT_PROXY_BYPASS_FOR_TESTING;
if (bypass)
proxy.noProxy = bypass.split(",");
return proxy;
}
var Network;
((Network2) => {
let SameSite;
((SameSite2) => {
SameSite2["Strict"] = "strict";
SameSite2["Lax"] = "lax";
SameSite2["None"] = "none";
})(SameSite = Network2.SameSite || (Network2.SameSite = {}));
})(Network || (Network = {}));
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
BidiBrowser,
BidiBrowserContext,
Network
});

View File

@@ -0,0 +1,153 @@
"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 bidiChromium_exports = {};
__export(bidiChromium_exports, {
BidiChromium: () => BidiChromium
});
module.exports = __toCommonJS(bidiChromium_exports);
var import_os = __toESM(require("os"));
var import_ascii = require("../utils/ascii");
var import_browserType = require("../browserType");
var import_bidiBrowser = require("./bidiBrowser");
var import_bidiConnection = require("./bidiConnection");
var import_chromiumSwitches = require("../chromium/chromiumSwitches");
var import_chromium = require("../chromium/chromium");
class BidiChromium extends import_browserType.BrowserType {
constructor(parent) {
super(parent, "_bidiChromium");
}
async connectToTransport(transport, options, browserLogsCollector) {
const bidiTransport = await require("./bidiOverCdp").connectBidiOverCdp(transport);
transport[kBidiOverCdpWrapper] = bidiTransport;
try {
return import_bidiBrowser.BidiBrowser.connect(this.attribution.playwright, bidiTransport, options);
} catch (e) {
if (browserLogsCollector.recentLogs().some((log) => log.includes("Failed to create a ProcessSingleton for your profile directory."))) {
throw new Error(
"Failed to create a ProcessSingleton for your profile directory. This usually means that the profile is already in use by another instance of Chromium."
);
}
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 = [
`Chromium sandboxing failed!`,
`================================`,
`To avoid the sandboxing issue, do either of the following:`,
` - (preferred): Configure your environment to support sandboxing`,
` - (alternative): Launch Chromium without sandbox using 'chromiumSandbox: false' option`,
`================================`,
``
].join("\n");
return error;
}
amendEnvironment(env) {
return env;
}
attemptToGracefullyCloseBrowser(transport) {
const bidiTransport = transport[kBidiOverCdpWrapper];
if (bidiTransport)
transport = bidiTransport;
transport.send({ method: "browser.close", params: {}, id: import_bidiConnection.kBrowserCloseMessageId });
}
supportsPipeTransport() {
return false;
}
defaultArgs(options, isPersistent, userDataDir) {
const chromeArguments = this._innerDefaultArgs(options);
chromeArguments.push(`--user-data-dir=${userDataDir}`);
chromeArguments.push("--remote-debugging-port=0");
if (isPersistent)
chromeArguments.push("about:blank");
else
chromeArguments.push("--no-startup-window");
return chromeArguments;
}
async waitForReadyState(options, browserLogsCollector) {
return (0, import_chromium.waitForReadyState)({ ...options, cdpPort: 0 }, browserLogsCollector);
}
_innerDefaultArgs(options) {
const { args = [] } = options;
const userDataDirArg = args.find((arg) => arg.startsWith("--user-data-dir"));
if (userDataDirArg)
throw this._createUserDataDirArgMisuseError("--user-data-dir");
if (args.find((arg) => arg.startsWith("--remote-debugging-pipe")))
throw new Error("Playwright manages remote debugging connection itself.");
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") {
chromeArguments.push("--enable-unsafe-swiftshader");
}
if (options.devtools)
chromeArguments.push("--auto-open-devtools-for-tabs");
if (options.headless) {
chromeArguments.push("--headless");
chromeArguments.push(
"--hide-scrollbars",
"--mute-audio",
"--blink-settings=primaryHoverType=2,availableHoverTypes=2,primaryPointerType=4,availablePointerTypes=4"
);
}
if (options.chromiumSandbox !== true)
chromeArguments.push("--no-sandbox");
const proxy = options.proxyOverride || options.proxy;
if (proxy) {
const proxyURL = new URL(proxy.server);
const isSocks = proxyURL.protocol === "socks5:";
if (isSocks && !options.socksProxyPort) {
chromeArguments.push(`--host-resolver-rules="MAP * ~NOTFOUND , EXCLUDE ${proxyURL.hostname}"`);
}
chromeArguments.push(`--proxy-server=${proxy.server}`);
const proxyBypassRules = [];
if (options.socksProxyPort)
proxyBypassRules.push("<-loopback>");
if (proxy.bypass)
proxyBypassRules.push(...proxy.bypass.split(",").map((t) => t.trim()).map((t) => t.startsWith(".") ? "*" + t : t));
if (!process.env.PLAYWRIGHT_DISABLE_FORCED_CHROMIUM_PROXIED_LOOPBACK && !proxyBypassRules.includes("<-loopback>"))
proxyBypassRules.push("<-loopback>");
if (proxyBypassRules.length > 0)
chromeArguments.push(`--proxy-bypass-list=${proxyBypassRules.join(";")}`);
}
chromeArguments.push(...args);
return chromeArguments;
}
}
const kBidiOverCdpWrapper = Symbol("kBidiConnectionWrapper");
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
BidiChromium
});

View File

@@ -0,0 +1,187 @@
"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 bidiConnection_exports = {};
__export(bidiConnection_exports, {
BidiConnection: () => BidiConnection,
BidiSession: () => BidiSession,
kBrowserCloseMessageId: () => kBrowserCloseMessageId
});
module.exports = __toCommonJS(bidiConnection_exports);
var import_events = require("events");
var import_debugLogger = require("../utils/debugLogger");
var import_helper = require("../helper");
var import_protocolError = require("../protocolError");
const kBrowserCloseMessageId = 0;
class BidiConnection {
constructor(transport, onDisconnect, protocolLogger, browserLogsCollector) {
this._lastId = 0;
this._closed = false;
this._browsingContextToSession = /* @__PURE__ */ new Map();
this._transport = transport;
this._onDisconnect = onDisconnect;
this._protocolLogger = protocolLogger;
this._browserLogsCollector = browserLogsCollector;
this.browserSession = new BidiSession(this, "", (message) => {
this.rawSend(message);
});
this._transport.onmessage = this._dispatchMessage.bind(this);
this._transport.onclose = this._onClose.bind(this);
}
nextMessageId() {
return ++this._lastId;
}
rawSend(message) {
this._protocolLogger("send", message);
this._transport.send(message);
}
_dispatchMessage(message) {
this._protocolLogger("receive", message);
const object = message;
if (object.type === "event") {
let context;
if ("context" in object.params)
context = object.params.context;
else if (object.method === "log.entryAdded" || object.method === "script.message")
context = object.params.source?.context;
if (context) {
const session = this._browsingContextToSession.get(context);
if (session) {
session.dispatchMessage(message);
return;
}
}
} else if (message.id) {
for (const session of this._browsingContextToSession.values()) {
if (session.hasCallback(message.id)) {
session.dispatchMessage(message);
return;
}
}
}
this.browserSession.dispatchMessage(message);
}
_onClose(reason) {
this._closed = true;
this._transport.onmessage = void 0;
this._transport.onclose = void 0;
this._browserDisconnectedLogs = import_helper.helper.formatBrowserLogs(this._browserLogsCollector.recentLogs(), reason);
this.browserSession.dispose();
this._onDisconnect();
}
isClosed() {
return this._closed;
}
close() {
if (!this._closed)
this._transport.close();
}
createMainFrameBrowsingContextSession(bowsingContextId) {
const result = new BidiSession(this, bowsingContextId, (message) => this.rawSend(message));
this._browsingContextToSession.set(bowsingContextId, result);
return result;
}
}
class BidiSession extends import_events.EventEmitter {
constructor(connection, sessionId, rawSend) {
super();
this._disposed = false;
this._callbacks = /* @__PURE__ */ new Map();
this._crashed = false;
this._browsingContexts = /* @__PURE__ */ new Set();
this.setMaxListeners(0);
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;
}
addFrameBrowsingContext(context) {
this._browsingContexts.add(context);
this.connection._browsingContextToSession.set(context, this);
}
removeFrameBrowsingContext(context) {
this._browsingContexts.delete(context);
this.connection._browsingContextToSession.delete(context);
}
async send(method, params) {
if (this._crashed || this._disposed || this.connection._browserDisconnectedLogs)
throw new import_protocolError.ProtocolError(this._crashed ? "crashed" : "closed", void 0, this.connection._browserDisconnectedLogs);
const id = this.connection.nextMessageId();
const messageObj = { id, method, params };
this._rawSend(messageObj);
return new Promise((resolve, reject) => {
this._callbacks.set(id, { resolve, reject, error: new import_protocolError.ProtocolError("error", method) });
});
}
sendMayFail(method, params) {
return this.send(method, params).catch((error) => import_debugLogger.debugLogger.log("error", error));
}
markAsCrashed() {
this._crashed = true;
}
isDisposed() {
return this._disposed;
}
dispose() {
this._disposed = true;
this.connection._browsingContextToSession.delete(this.sessionId);
for (const context of this._browsingContexts)
this.connection._browsingContextToSession.delete(context);
this._browsingContexts.clear();
for (const callback of this._callbacks.values()) {
callback.error.type = this._crashed ? "crashed" : "closed";
callback.error.logs = this.connection._browserDisconnectedLogs;
callback.reject(callback.error);
}
this._callbacks.clear();
}
hasCallback(id) {
return this._callbacks.has(id);
}
dispatchMessage(message) {
const object = message;
if (object.id === kBrowserCloseMessageId)
return;
if (object.id && this._callbacks.has(object.id)) {
const callback = this._callbacks.get(object.id);
this._callbacks.delete(object.id);
if (object.type === "error") {
callback.error.setMessage(object.error + "\nMessage: " + object.message);
callback.reject(callback.error);
} else if (object.type === "success") {
callback.resolve(object.result);
} else {
callback.error.setMessage("Internal error, unexpected response type: " + JSON.stringify(object));
callback.reject(callback.error);
}
} else if (object.id) {
} else {
Promise.resolve().then(() => this.emit(object.method, object.params));
}
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
BidiConnection,
BidiSession,
kBrowserCloseMessageId
});

View File

@@ -0,0 +1,221 @@
"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 bidiExecutionContext_exports = {};
__export(bidiExecutionContext_exports, {
BidiExecutionContext: () => BidiExecutionContext,
createHandle: () => createHandle
});
module.exports = __toCommonJS(bidiExecutionContext_exports);
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");
class BidiExecutionContext {
constructor(session, realmInfo) {
this._session = session;
if (realmInfo.type === "window") {
this._target = {
context: realmInfo.context,
sandbox: realmInfo.sandbox
};
} else {
this._target = {
realm: realmInfo.realm
};
}
}
async rawEvaluateJSON(expression) {
const response = await this._session.send("script.evaluate", {
expression,
target: this._target,
serializationOptions: {
maxObjectDepth: 10,
maxDomDepth: 10
},
awaitPromise: true,
userActivation: true
});
if (response.type === "success")
return import_bidiDeserializer.BidiDeserializer.deserialize(response.result);
if (response.type === "exception")
throw new js.JavaScriptErrorInEvaluate(response.exceptionDetails.text + "\nFull val: " + JSON.stringify(response.exceptionDetails));
throw new js.JavaScriptErrorInEvaluate("Unexpected response type: " + JSON.stringify(response));
}
async rawEvaluateHandle(context, expression) {
const response = await this._session.send("script.evaluate", {
expression,
target: this._target,
resultOwnership: bidi.Script.ResultOwnership.Root,
// Necessary for the handle to be returned.
serializationOptions: { maxObjectDepth: 0, maxDomDepth: 0 },
awaitPromise: true,
userActivation: true
});
if (response.type === "success") {
if ("handle" in response.result)
return createHandle(context, response.result);
throw new js.JavaScriptErrorInEvaluate("Cannot get handle: " + JSON.stringify(response.result));
}
if (response.type === "exception")
throw new js.JavaScriptErrorInEvaluate(response.exceptionDetails.text + "\nFull val: " + JSON.stringify(response.exceptionDetails));
throw new js.JavaScriptErrorInEvaluate("Unexpected response type: " + JSON.stringify(response));
}
async evaluateWithArguments(functionDeclaration, returnByValue, utilityScript, values, handles) {
const response = await this._session.send("script.callFunction", {
functionDeclaration,
target: this._target,
arguments: [
{ handle: utilityScript._objectId },
...values.map(import_bidiSerializer.BidiSerializer.serialize),
...handles.map((handle) => ({ handle: handle._objectId }))
],
resultOwnership: returnByValue ? void 0 : bidi.Script.ResultOwnership.Root,
// Necessary for the handle to be returned.
serializationOptions: returnByValue ? {} : { maxObjectDepth: 0, maxDomDepth: 0 },
awaitPromise: true,
userActivation: true
});
if (response.type === "exception")
throw new js.JavaScriptErrorInEvaluate(response.exceptionDetails.text + "\nFull val: " + JSON.stringify(response.exceptionDetails));
if (response.type === "success") {
if (returnByValue)
return (0, import_utilityScriptSerializers.parseEvaluationResultValue)(import_bidiDeserializer.BidiDeserializer.deserialize(response.result));
return createHandle(utilityScript._context, response.result);
}
throw new js.JavaScriptErrorInEvaluate("Unexpected response type: " + JSON.stringify(response));
}
async getProperties(handle) {
const names = await handle.evaluate((object) => {
const names2 = [];
const descriptors = Object.getOwnPropertyDescriptors(object);
for (const name in descriptors) {
if (descriptors[name]?.enumerable)
names2.push(name);
}
return names2;
});
const values = await Promise.all(names.map((name) => handle.evaluateHandle((object, name2) => object[name2], name)));
const map = /* @__PURE__ */ new Map();
for (let i = 0; i < names.length; i++)
map.set(names[i], values[i]);
return map;
}
async releaseHandle(handle) {
if (!handle._objectId)
return;
await this._session.send("script.disown", {
target: this._target,
handles: [handle._objectId]
});
}
async nodeIdForElementHandle(handle) {
const shared = await this._remoteValueForReference({ handle: handle._objectId });
if (!("sharedId" in shared))
throw new Error("Element is not a node");
return {
sharedId: shared.sharedId
};
}
async remoteObjectForNodeId(context, nodeId) {
const result = await this._remoteValueForReference(nodeId, true);
if (!("handle" in result))
throw new Error("Can't get remote object for nodeId");
return createHandle(context, result);
}
async contentFrameIdForFrame(handle) {
const contentWindow = await this._rawCallFunction("e => e.contentWindow", { handle: handle._objectId });
if (contentWindow?.type === "window")
return contentWindow.value.context;
return null;
}
async frameIdForWindowHandle(handle) {
if (!handle._objectId)
throw new Error("JSHandle is not a DOM node handle");
const contentWindow = await this._remoteValueForReference({ handle: handle._objectId });
if (contentWindow.type === "window")
return contentWindow.value.context;
return null;
}
async _remoteValueForReference(reference, createHandle2) {
return await this._rawCallFunction("e => e", reference, createHandle2);
}
async _rawCallFunction(functionDeclaration, arg, createHandle2) {
const response = await this._session.send("script.callFunction", {
functionDeclaration,
target: this._target,
arguments: [arg],
// "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,
userActivation: true
});
if (response.type === "exception")
throw new js.JavaScriptErrorInEvaluate(response.exceptionDetails.text + "\nFull val: " + JSON.stringify(response.exceptionDetails));
if (response.type === "success")
return response.result;
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 createHandle(context, remoteObject) {
if (remoteObject.type === "node") {
(0, import_utils.assert)(context instanceof dom.FrameExecutionContext);
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));
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
BidiExecutionContext,
createHandle
});

View File

@@ -0,0 +1,115 @@
"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 bidiFirefox_exports = {};
__export(bidiFirefox_exports, {
BidiFirefox: () => BidiFirefox
});
module.exports = __toCommonJS(bidiFirefox_exports);
var import_os = __toESM(require("os"));
var import_path = __toESM(require("path"));
var import_ascii = require("../utils/ascii");
var import_browserType = require("../browserType");
var import_bidiBrowser = require("./bidiBrowser");
var import_bidiConnection = require("./bidiConnection");
var import_firefoxPrefs = require("./third_party/firefoxPrefs");
var import_manualPromise = require("../../utils/isomorphic/manualPromise");
class BidiFirefox extends import_browserType.BrowserType {
constructor(parent) {
super(parent, "_bidiFirefox");
}
executablePath() {
return "";
}
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.
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;
}
amendEnvironment(env) {
if (!import_path.default.isAbsolute(import_os.default.homedir()))
throw new Error(`Cannot launch Firefox with relative home directory. Did you set ${import_os.default.platform() === "win32" ? "USERPROFILE" : "HOME"} to a relative path?`);
env = {
...env,
"MOZ_CRASHREPORTER": "1",
"MOZ_CRASHREPORTER_NO_REPORT": "1",
"MOZ_CRASHREPORTER_SHUTDOWN": "1"
};
if (import_os.default.platform() === "linux") {
return { ...env, SNAP_NAME: void 0, SNAP_INSTANCE_NAME: void 0 };
}
return env;
}
attemptToGracefullyCloseBrowser(transport) {
transport.send({ method: "browser.close", params: {}, id: import_bidiConnection.kBrowserCloseMessageId });
}
supportsPipeTransport() {
return false;
}
async prepareUserDataDir(options, userDataDir) {
await (0, import_firefoxPrefs.createProfile)({
path: userDataDir,
preferences: options.firefoxUserPrefs || {}
});
}
defaultArgs(options, isPersistent, userDataDir) {
const { args = [], headless } = options;
const userDataDirArg = args.find((arg) => arg.startsWith("-profile") || arg.startsWith("--profile"));
if (userDataDirArg)
throw this._createUserDataDirArgMisuseError("--profile");
const firefoxArguments = ["--remote-debugging-port=0"];
if (headless)
firefoxArguments.push("--headless");
else
firefoxArguments.push("--foreground");
firefoxArguments.push(`--profile`, userDataDir);
firefoxArguments.push(...args);
return firefoxArguments;
}
async waitForReadyState(options, browserLogsCollector) {
const result = new import_manualPromise.ManualPromise();
browserLogsCollector.onMessage((message) => {
const match = message.match(/WebDriver BiDi listening on (ws:\/\/.*)$/);
if (match)
result.resolve({ wsEndpoint: match[1] + "/session" });
});
return result;
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
BidiFirefox
});

View File

@@ -0,0 +1,146 @@
"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 bidiInput_exports = {};
__export(bidiInput_exports, {
RawKeyboardImpl: () => RawKeyboardImpl,
RawMouseImpl: () => RawMouseImpl,
RawTouchscreenImpl: () => RawTouchscreenImpl
});
module.exports = __toCommonJS(bidiInput_exports);
var import_input = require("../input");
var import_bidiKeyboard = require("./third_party/bidiKeyboard");
var bidi = __toESM(require("./third_party/bidiProtocol"));
class RawKeyboardImpl {
constructor(session) {
this._session = session;
}
setSession(session) {
this._session = session;
}
async keydown(progress, modifiers, keyName, description, autoRepeat) {
keyName = (0, import_input.resolveSmartModifierString)(keyName);
const actions = [];
actions.push({ type: "keyDown", value: (0, import_bidiKeyboard.getBidiKeyValue)(keyName) });
await this._performActions(progress, actions);
}
async keyup(progress, modifiers, keyName, description) {
keyName = (0, import_input.resolveSmartModifierString)(keyName);
const actions = [];
actions.push({ type: "keyUp", value: (0, import_bidiKeyboard.getBidiKeyValue)(keyName) });
await this._performActions(progress, actions);
}
async sendText(progress, text) {
const actions = [];
for (const char of text) {
const value = (0, import_bidiKeyboard.getBidiKeyValue)(char);
actions.push({ type: "keyDown", value });
actions.push({ type: "keyUp", value });
}
await this._performActions(progress, actions);
}
async _performActions(progress, actions) {
await progress.race(this._session.send("input.performActions", {
context: this._session.sessionId,
actions: [
{
type: "key",
id: "pw_keyboard",
actions
}
]
}));
}
}
class RawMouseImpl {
constructor(session) {
this._session = session;
}
async move(progress, x, y, button, buttons, modifiers, forClick) {
await this._performActions(progress, [{ type: "pointerMove", x, y }]);
}
async down(progress, x, y, button, buttons, modifiers, clickCount) {
await this._performActions(progress, [{ type: "pointerDown", button: toBidiButton(button) }]);
}
async up(progress, x, y, button, buttons, modifiers, clickCount) {
await this._performActions(progress, [{ type: "pointerUp", button: toBidiButton(button) }]);
}
async wheel(progress, x, y, buttons, modifiers, deltaX, deltaY) {
x = Math.floor(x);
y = Math.floor(y);
await progress.race(this._session.send("input.performActions", {
context: this._session.sessionId,
actions: [
{
type: "wheel",
id: "pw_mouse_wheel",
actions: [{ type: "scroll", x, y, deltaX, deltaY }]
}
]
}));
}
async _performActions(progress, actions) {
await progress.race(this._session.send("input.performActions", {
context: this._session.sessionId,
actions: [
{
type: "pointer",
id: "pw_mouse",
parameters: {
pointerType: bidi.Input.PointerType.Mouse
},
actions
}
]
}));
}
}
class RawTouchscreenImpl {
constructor(session) {
this._session = session;
}
async tap(progress, x, y, modifiers) {
}
}
function toBidiButton(button) {
switch (button) {
case "left":
return 0;
case "right":
return 2;
case "middle":
return 1;
}
throw new Error("Unknown button: " + button);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
RawKeyboardImpl,
RawMouseImpl,
RawTouchscreenImpl
});

View File

@@ -0,0 +1,317 @@
"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 bidiNetworkManager_exports = {};
__export(bidiNetworkManager_exports, {
BidiNetworkManager: () => BidiNetworkManager,
bidiBytesValueToString: () => bidiBytesValueToString
});
module.exports = __toCommonJS(bidiNetworkManager_exports);
var import_eventsHelper = require("../utils/eventsHelper");
var import_cookieStore = require("../cookieStore");
var network = __toESM(require("../network"));
var bidi = __toESM(require("./third_party/bidiProtocol"));
class BidiNetworkManager {
constructor(bidiSession, page) {
this._userRequestInterceptionEnabled = false;
this._protocolRequestInterceptionEnabled = false;
this._session = bidiSession;
this._requests = /* @__PURE__ */ new Map();
this._page = page;
this._eventListeners = [
import_eventsHelper.eventsHelper.addEventListener(bidiSession, "network.beforeRequestSent", this._onBeforeRequestSent.bind(this)),
import_eventsHelper.eventsHelper.addEventListener(bidiSession, "network.responseStarted", this._onResponseStarted.bind(this)),
import_eventsHelper.eventsHelper.addEventListener(bidiSession, "network.responseCompleted", this._onResponseCompleted.bind(this)),
import_eventsHelper.eventsHelper.addEventListener(bidiSession, "network.fetchError", this._onFetchError.bind(this)),
import_eventsHelper.eventsHelper.addEventListener(bidiSession, "network.authRequired", this._onAuthRequired.bind(this))
];
}
dispose() {
import_eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
}
_onBeforeRequestSent(param) {
if (param.request.url.startsWith("data:"))
return;
const redirectedFrom = param.redirectCount ? this._requests.get(param.request.request) || null : null;
const frame = redirectedFrom ? redirectedFrom.request.frame() : param.context ? this._page.frameManager.frame(param.context) : null;
if (!frame)
return;
if (redirectedFrom)
this._requests.delete(redirectedFrom._id);
let route;
if (param.intercepts) {
if (redirectedFrom) {
let params = {};
if (redirectedFrom._originalRequestRoute?._alreadyContinuedHeaders)
params = toBidiRequestHeaders(redirectedFrom._originalRequestRoute._alreadyContinuedHeaders ?? []);
this._session.sendMayFail("network.continueRequest", {
request: param.request.request,
...params
});
} else {
route = new BidiRouteImpl(this._session, param.request.request);
}
}
const request = new BidiRequest(frame, redirectedFrom, param, route);
this._requests.set(request._id, request);
this._page.frameManager.requestStarted(request.request, route);
}
_onResponseStarted(params) {
const request = this._requests.get(params.request.request);
if (!request)
return;
const getResponseBody = async () => {
throw new Error(`Response body is not available for requests in Bidi`);
};
const timings = params.request.timings;
const startTime = timings.requestTime;
function relativeToStart(time) {
if (!time)
return -1;
return time - startTime;
}
const timing = {
startTime,
requestStart: relativeToStart(timings.requestStart),
responseStart: relativeToStart(timings.responseStart),
domainLookupStart: relativeToStart(timings.dnsStart),
domainLookupEnd: relativeToStart(timings.dnsEnd),
connectStart: relativeToStart(timings.connectStart),
secureConnectionStart: relativeToStart(timings.tlsStart),
connectEnd: relativeToStart(timings.connectEnd)
};
const response = new network.Response(request.request, params.response.status, params.response.statusText, fromBidiHeaders(params.response.headers), timing, getResponseBody, false);
response._serverAddrFinished();
response._securityDetailsFinished();
response.setRawResponseHeaders(null);
response.setResponseHeadersSize(params.response.headersSize);
this._page.frameManager.requestReceivedResponse(response);
}
_onResponseCompleted(params) {
const request = this._requests.get(params.request.request);
if (!request)
return;
const response = request.request._existingResponse();
response.setTransferSize(params.response.bodySize);
response.setEncodedBodySize(params.response.bodySize);
const isRedirected = response.status() >= 300 && response.status() <= 399;
const responseEndTime = params.request.timings.responseEnd - response.timing().startTime;
if (isRedirected) {
response._requestFinished(responseEndTime);
} else {
this._requests.delete(request._id);
response._requestFinished(responseEndTime);
}
response._setHttpVersion(params.response.protocol);
this._page.frameManager.reportRequestFinished(request.request, response);
}
_onFetchError(params) {
const request = this._requests.get(params.request.request);
if (!request)
return;
this._requests.delete(request._id);
const response = request.request._existingResponse();
if (response) {
response.setTransferSize(null);
response.setEncodedBodySize(null);
response._requestFinished(-1);
}
request.request._setFailureText(params.errorText);
this._page.frameManager.requestFailed(request.request, params.errorText === "NS_BINDING_ABORTED");
}
_onAuthRequired(params) {
const isBasic = params.response.authChallenges?.some((challenge) => challenge.scheme.startsWith("Basic"));
const credentials = this._page.browserContext._options.httpCredentials;
if (isBasic && credentials) {
this._session.sendMayFail("network.continueWithAuth", {
request: params.request.request,
action: "provideCredentials",
credentials: {
type: "password",
username: credentials.username,
password: credentials.password
}
});
} else {
this._session.sendMayFail("network.continueWithAuth", {
request: params.request.request,
action: "default"
});
}
}
async setRequestInterception(value) {
this._userRequestInterceptionEnabled = value;
await this._updateProtocolRequestInterception();
}
async setCredentials(credentials) {
this._credentials = credentials;
await this._updateProtocolRequestInterception();
}
async _updateProtocolRequestInterception(initial) {
const enabled = this._userRequestInterceptionEnabled || !!this._credentials;
if (enabled === this._protocolRequestInterceptionEnabled)
return;
this._protocolRequestInterceptionEnabled = enabled;
if (initial && !enabled)
return;
const cachePromise = this._session.send("network.setCacheBehavior", { cacheBehavior: enabled ? "bypass" : "default" });
let interceptPromise = Promise.resolve(void 0);
if (enabled) {
interceptPromise = this._session.send("network.addIntercept", {
phases: [bidi.Network.InterceptPhase.AuthRequired, bidi.Network.InterceptPhase.BeforeRequestSent],
urlPatterns: [{ type: "pattern" }]
// urlPatterns: [{ type: 'string', pattern: '*' }],
}).then((r) => {
this._intercepId = r.intercept;
});
} else if (this._intercepId) {
interceptPromise = this._session.send("network.removeIntercept", { intercept: this._intercepId });
this._intercepId = void 0;
}
await Promise.all([cachePromise, interceptPromise]);
}
}
class BidiRequest {
constructor(frame, redirectedFrom, payload, route) {
this._id = payload.request.request;
if (redirectedFrom)
redirectedFrom._redirectedTo = this;
const postDataBuffer = null;
this.request = new network.Request(
frame._page.browserContext,
frame,
null,
redirectedFrom ? redirectedFrom.request : null,
payload.navigation ?? void 0,
payload.request.url,
"other",
payload.request.method,
postDataBuffer,
fromBidiHeaders(payload.request.headers)
);
this.request.setRawRequestHeaders(null);
this.request._setBodySize(payload.request.bodySize || 0);
this._originalRequestRoute = route ?? redirectedFrom?._originalRequestRoute;
route?._setRequest(this.request);
}
_finalRequest() {
let request = this;
while (request._redirectedTo)
request = request._redirectedTo;
return request;
}
}
class BidiRouteImpl {
constructor(session, requestId) {
this._session = session;
this._requestId = requestId;
}
_setRequest(request) {
this._request = request;
}
async continue(overrides) {
let headers = overrides.headers || this._request.headers();
if (overrides.postData && headers) {
headers = headers.map((header) => {
if (header.name.toLowerCase() === "content-length")
return { name: header.name, value: overrides.postData.byteLength.toString() };
return header;
});
}
this._alreadyContinuedHeaders = headers;
await this._session.sendMayFail("network.continueRequest", {
request: this._requestId,
url: overrides.url,
method: overrides.method,
...toBidiRequestHeaders(this._alreadyContinuedHeaders),
body: overrides.postData ? { type: "base64", value: Buffer.from(overrides.postData).toString("base64") } : void 0
});
}
async fulfill(response) {
const base64body = response.isBase64 ? response.body : Buffer.from(response.body).toString("base64");
await this._session.sendMayFail("network.provideResponse", {
request: this._requestId,
statusCode: response.status,
reasonPhrase: network.statusText(response.status),
...toBidiResponseHeaders(response.headers),
body: { type: "base64", value: base64body }
});
}
async abort(errorCode) {
await this._session.sendMayFail("network.failRequest", {
request: this._requestId
});
}
}
function fromBidiHeaders(bidiHeaders) {
const result = [];
for (const { name, value } of bidiHeaders)
result.push({ name, value: bidiBytesValueToString(value) });
return result;
}
function toBidiRequestHeaders(allHeaders) {
const bidiHeaders = toBidiHeaders(allHeaders);
return { headers: bidiHeaders };
}
function toBidiResponseHeaders(headers) {
const setCookieHeaders = headers.filter((h) => h.name.toLowerCase() === "set-cookie");
const otherHeaders = headers.filter((h) => h.name.toLowerCase() !== "set-cookie");
const rawCookies = setCookieHeaders.map((h) => (0, import_cookieStore.parseRawCookie)(h.value));
const cookies = rawCookies.filter(Boolean).map((c) => {
return {
...c,
value: { type: "string", value: c.value },
sameSite: toBidiSameSite(c.sameSite)
};
});
return { cookies, headers: toBidiHeaders(otherHeaders) };
}
function toBidiHeaders(headers) {
return headers.map(({ name, value }) => ({ name, value: { type: "string", value } }));
}
function bidiBytesValueToString(value) {
if (value.type === "string")
return value.value;
if (value.type === "base64")
return Buffer.from(value.type, "base64").toString("binary");
return "unknown value type: " + value.type;
}
function toBidiSameSite(sameSite) {
if (!sameSite)
return void 0;
if (sameSite === "Strict")
return bidi.Network.SameSite.Strict;
if (sameSite === "Lax")
return bidi.Network.SameSite.Lax;
return bidi.Network.SameSite.None;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
BidiNetworkManager,
bidiBytesValueToString
});

View File

@@ -0,0 +1,102 @@
"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 bidiOverCdp_exports = {};
__export(bidiOverCdp_exports, {
connectBidiOverCdp: () => connectBidiOverCdp
});
module.exports = __toCommonJS(bidiOverCdp_exports);
var bidiMapper = __toESM(require("chromium-bidi/lib/cjs/bidiMapper/BidiMapper"));
var bidiCdpConnection = __toESM(require("chromium-bidi/lib/cjs/cdp/CdpConnection"));
var import_debugLogger = require("../utils/debugLogger");
const bidiServerLogger = (prefix, ...args) => {
import_debugLogger.debugLogger.log(prefix, args);
};
async function connectBidiOverCdp(cdp) {
let server = void 0;
const bidiTransport = new BidiTransportImpl();
const bidiConnection = new BidiConnection(bidiTransport, () => server?.close());
const cdpTransportImpl = new CdpTransportImpl(cdp);
const cdpConnection = new bidiCdpConnection.MapperCdpConnection(cdpTransportImpl, bidiServerLogger);
cdp.onclose = () => bidiConnection.onclose?.();
server = await bidiMapper.BidiServer.createAndStart(
bidiTransport,
cdpConnection,
await cdpConnection.createBrowserSession(),
/* selfTargetId= */
"",
void 0,
bidiServerLogger
);
return bidiConnection;
}
class BidiTransportImpl {
setOnMessage(handler) {
this._handler = handler;
}
sendMessage(message) {
return this._bidiConnection.onmessage?.(message);
}
close() {
this._bidiConnection.onclose?.();
}
}
class BidiConnection {
constructor(bidiTransport, closeCallback) {
this._bidiTransport = bidiTransport;
this._bidiTransport._bidiConnection = this;
this._closeCallback = closeCallback;
}
send(s) {
this._bidiTransport._handler?.(s);
}
close() {
this._closeCallback();
}
}
class CdpTransportImpl {
constructor(connection) {
this._connection = connection;
this._connection.onmessage = (message) => {
this._handler?.(JSON.stringify(message));
};
}
setOnMessage(handler) {
this._handler = handler;
}
sendMessage(message) {
return this._connection.send(JSON.parse(message));
}
close() {
this._connection.close();
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
connectBidiOverCdp
});

View File

@@ -0,0 +1,486 @@
"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 bidiPage_exports = {};
__export(bidiPage_exports, {
BidiPage: () => BidiPage,
kPlaywrightBindingChannel: () => kPlaywrightBindingChannel
});
module.exports = __toCommonJS(bidiPage_exports);
var import_eventsHelper = require("../utils/eventsHelper");
var dialog = __toESM(require("../dialog"));
var dom = __toESM(require("../dom"));
var import_page = require("../page");
var import_bidiExecutionContext = require("./bidiExecutionContext");
var import_bidiInput = require("./bidiInput");
var import_bidiNetworkManager = require("./bidiNetworkManager");
var import_bidiPdf = require("./bidiPdf");
var bidi = __toESM(require("./third_party/bidiProtocol"));
const UTILITY_WORLD_NAME = "__playwright_utility_world__";
const kPlaywrightBindingChannel = "playwrightChannel";
class BidiPage {
constructor(browserContext, bidiSession, opener) {
this._sessionListeners = [];
this._initScriptIds = /* @__PURE__ */ new Map();
this._session = bidiSession;
this._opener = opener;
this.rawKeyboard = new import_bidiInput.RawKeyboardImpl(bidiSession);
this.rawMouse = new import_bidiInput.RawMouseImpl(bidiSession);
this.rawTouchscreen = new import_bidiInput.RawTouchscreenImpl(bidiSession);
this._realmToContext = /* @__PURE__ */ new Map();
this._page = new import_page.Page(this, browserContext);
this._browserContext = browserContext;
this._networkManager = new import_bidiNetworkManager.BidiNetworkManager(this._session, this._page);
this._pdf = new import_bidiPdf.BidiPDF(this._session);
this._page.on(import_page.Page.Events.FrameDetached, (frame) => this._removeContextsForFrame(frame, false));
this._sessionListeners = [
import_eventsHelper.eventsHelper.addEventListener(bidiSession, "script.realmCreated", this._onRealmCreated.bind(this)),
import_eventsHelper.eventsHelper.addEventListener(bidiSession, "script.message", this._onScriptMessage.bind(this)),
import_eventsHelper.eventsHelper.addEventListener(bidiSession, "browsingContext.contextDestroyed", this._onBrowsingContextDestroyed.bind(this)),
import_eventsHelper.eventsHelper.addEventListener(bidiSession, "browsingContext.navigationStarted", this._onNavigationStarted.bind(this)),
import_eventsHelper.eventsHelper.addEventListener(bidiSession, "browsingContext.navigationCommitted", this._onNavigationCommitted.bind(this)),
import_eventsHelper.eventsHelper.addEventListener(bidiSession, "browsingContext.navigationAborted", this._onNavigationAborted.bind(this)),
import_eventsHelper.eventsHelper.addEventListener(bidiSession, "browsingContext.navigationFailed", this._onNavigationFailed.bind(this)),
import_eventsHelper.eventsHelper.addEventListener(bidiSession, "browsingContext.fragmentNavigated", this._onFragmentNavigated.bind(this)),
import_eventsHelper.eventsHelper.addEventListener(bidiSession, "browsingContext.historyUpdated", this._onHistoryUpdated.bind(this)),
import_eventsHelper.eventsHelper.addEventListener(bidiSession, "browsingContext.domContentLoaded", this._onDomContentLoaded.bind(this)),
import_eventsHelper.eventsHelper.addEventListener(bidiSession, "browsingContext.load", this._onLoad.bind(this)),
import_eventsHelper.eventsHelper.addEventListener(bidiSession, "browsingContext.userPromptOpened", this._onUserPromptOpened.bind(this)),
import_eventsHelper.eventsHelper.addEventListener(bidiSession, "log.entryAdded", this._onLogEntryAdded.bind(this))
];
this._initialize().then(
() => this._page.reportAsNew(this._opener?._page),
(error) => this._page.reportAsNew(this._opener?._page, error)
);
}
async _initialize() {
this._onFrameAttached(this._session.sessionId, null);
await Promise.all([
this.updateHttpCredentials(),
this.updateRequestInterception()
// 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.
]);
}
didClose() {
this._session.dispose();
import_eventsHelper.eventsHelper.removeEventListeners(this._sessionListeners);
this._page._didClose();
}
_onFrameAttached(frameId, parentFrameId) {
return this._page.frameManager.frameAttached(frameId, parentFrameId);
}
_removeContextsForFrame(frame, notifyFrame) {
for (const [contextId, context] of this._realmToContext) {
if (context.frame === frame) {
this._realmToContext.delete(contextId);
if (notifyFrame)
frame._contextDestroyed(context);
}
}
}
_onRealmCreated(realmInfo) {
if (this._realmToContext.has(realmInfo.realm))
return;
if (realmInfo.type !== "window")
return;
const frame = this._page.frameManager.frame(realmInfo.context);
if (!frame)
return;
let worldName;
if (!realmInfo.sandbox) {
worldName = "main";
this._touchUtilityWorld(realmInfo.context);
} else if (realmInfo.sandbox === UTILITY_WORLD_NAME) {
worldName = "utility";
} else {
return;
}
const delegate = new import_bidiExecutionContext.BidiExecutionContext(this._session, realmInfo);
const context = new dom.FrameExecutionContext(delegate, frame, worldName);
frame._contextCreated(worldName, context);
this._realmToContext.set(realmInfo.realm, context);
}
async _touchUtilityWorld(context) {
await this._session.sendMayFail("script.evaluate", {
expression: "1 + 1",
target: {
context,
sandbox: UTILITY_WORLD_NAME
},
serializationOptions: {
maxObjectDepth: 10,
maxDomDepth: 10
},
awaitPromise: true,
userActivation: true
});
}
_onRealmDestroyed(params) {
const context = this._realmToContext.get(params.realm);
if (!context)
return false;
this._realmToContext.delete(params.realm);
context.frame._contextDestroyed(context);
return true;
}
// TODO: route the message directly to the browser
_onBrowsingContextDestroyed(params) {
this._browserContext._browser._onBrowsingContextDestroyed(params);
}
_onNavigationStarted(params) {
const frameId = params.context;
this._page.frameManager.frameRequestedNavigation(frameId, params.navigation);
}
_onNavigationCommitted(params) {
const frameId = params.context;
this._page.frameManager.frameCommittedNewDocumentNavigation(
frameId,
params.url,
"",
params.navigation,
/* initial */
false
);
}
_onDomContentLoaded(params) {
const frameId = params.context;
this._page.frameManager.frameLifecycleEvent(frameId, "domcontentloaded");
}
_onLoad(params) {
this._page.frameManager.frameLifecycleEvent(params.context, "load");
}
_onNavigationAborted(params) {
this._page.frameManager.frameAbortedNavigation(params.context, "Navigation aborted", params.navigation || void 0);
}
_onNavigationFailed(params) {
this._page.frameManager.frameAbortedNavigation(params.context, "Navigation failed", params.navigation || void 0);
}
_onFragmentNavigated(params) {
this._page.frameManager.frameCommittedSameDocumentNavigation(params.context, params.url);
}
_onHistoryUpdated(params) {
this._page.frameManager.frameCommittedSameDocumentNavigation(params.context, params.url);
}
_onUserPromptOpened(event) {
this._page.browserContext.dialogManager.dialogDidOpen(new dialog.Dialog(
this._page,
event.type,
event.message,
async (accept, userText) => {
await this._session.send("browsingContext.handleUserPrompt", { context: event.context, accept, userText });
},
event.defaultValue
));
}
_onLogEntryAdded(params) {
if (params.type !== "console")
return;
const entry = params;
const context = this._realmToContext.get(params.source.realm);
if (!context)
return;
const callFrame = params.stackTrace?.callFrames[0];
const location = callFrame ?? { url: "", lineNumber: 1, columnNumber: 1 };
this._page.addConsoleMessage(entry.method, entry.args.map((arg) => (0, import_bidiExecutionContext.createHandle)(context, arg)), location, params.text || void 0);
}
async navigateFrame(frame, url, referrer) {
const { navigation } = await this._session.send("browsingContext.navigate", {
context: frame._id,
url
});
return { newDocumentId: navigation || void 0 };
}
async updateExtraHTTPHeaders() {
}
async updateEmulateMedia() {
}
async updateUserAgent() {
}
async bringToFront() {
await this._session.send("browsingContext.activate", {
context: this._session.sessionId
});
}
async updateEmulatedViewportSize() {
const options = this._browserContext._options;
const emulatedSize = this._page.emulatedSize();
if (!emulatedSize)
return;
const viewportSize = emulatedSize.viewport;
await this._session.send("browsingContext.setViewport", {
context: this._session.sessionId,
viewport: {
width: viewportSize.width,
height: viewportSize.height
},
devicePixelRatio: options.deviceScaleFactor || 1
});
}
async updateRequestInterception() {
await this._networkManager.setRequestInterception(this._page.needsRequestInterception());
}
async updateOffline() {
}
async updateHttpCredentials() {
await this._networkManager.setCredentials(this._browserContext._options.httpCredentials);
}
async updateFileChooserInterception() {
}
async reload() {
await this._session.send("browsingContext.reload", {
context: this._session.sessionId,
// ignoreCache: true,
wait: bidi.BrowsingContext.ReadinessState.Interactive
});
}
async goBack() {
return await this._session.send("browsingContext.traverseHistory", {
context: this._session.sessionId,
delta: -1
}).then(() => true).catch(() => false);
}
async goForward() {
return await this._session.send("browsingContext.traverseHistory", {
context: this._session.sessionId,
delta: 1
}).then(() => true).catch(() => false);
}
async requestGC() {
throw new Error("Method not implemented.");
}
async _onScriptMessage(event) {
if (event.channel !== kPlaywrightBindingChannel)
return;
const pageOrError = await this._page.waitForInitializedOrError();
if (pageOrError instanceof Error)
return;
const context = this._realmToContext.get(event.source.realm);
if (!context)
return;
if (event.data.type !== "string")
return;
await this._page.onBindingCalled(event.data.value, context);
}
async addInitScript(initScript) {
const { script } = await this._session.send("script.addPreloadScript", {
// TODO: remove function call from the source.
functionDeclaration: `() => { return ${initScript.source} }`,
// TODO: push to iframes?
contexts: [this._session.sessionId]
});
this._initScriptIds.set(initScript, script);
}
async removeInitScripts(initScripts) {
const ids = [];
for (const script of initScripts) {
const id = this._initScriptIds.get(script);
if (id)
ids.push(id);
this._initScriptIds.delete(script);
}
await Promise.all(ids.map((script) => this._session.send("script.removePreloadScript", { script })));
}
async closePage(runBeforeUnload) {
await this._session.send("browsingContext.close", {
context: this._session.sessionId,
promptUnload: runBeforeUnload
});
}
async setBackgroundColor(color) {
}
async takeScreenshot(progress, format, documentRect, viewportRect, quality, fitsViewport, scale) {
const rect = documentRect || viewportRect;
const { data } = await progress.race(this._session.send("browsingContext.captureScreenshot", {
context: this._session.sessionId,
format: {
type: `image/${format === "png" ? "png" : "jpeg"}`,
quality: quality ? quality / 100 : 0.8
},
origin: documentRect ? "document" : "viewport",
clip: {
type: "box",
...rect
}
}));
return Buffer.from(data, "base64");
}
async getContentFrame(handle) {
const executionContext = toBidiExecutionContext(handle._context);
const frameId = await executionContext.contentFrameIdForFrame(handle);
if (!frameId)
return null;
return this._page.frameManager.frame(frameId);
}
async getOwnerFrame(handle) {
const windowHandle = await handle.evaluateHandle((node) => {
const doc = node.ownerDocument ?? node;
return doc.defaultView;
});
if (!windowHandle)
return null;
const executionContext = toBidiExecutionContext(handle._context);
return executionContext.frameIdForWindowHandle(windowHandle);
}
async getBoundingBox(handle) {
const box = await handle.evaluate((element) => {
if (!(element instanceof Element))
return null;
const rect = element.getBoundingClientRect();
return { x: rect.x, y: rect.y, width: rect.width, height: rect.height };
});
if (!box)
return null;
const position = await this._framePosition(handle._frame);
if (!position)
return null;
box.x += position.x;
box.y += position.y;
return box;
}
// TODO: move to Frame.
async _framePosition(frame) {
if (frame === this._page.mainFrame())
return { x: 0, y: 0 };
const element = await frame.frameElement();
const box = await element.boundingBox();
if (!box)
return null;
const style = await element.evaluateInUtility(([injected, iframe]) => injected.describeIFrameStyle(iframe), {}).catch((e) => "error:notconnected");
if (style === "error:notconnected" || style === "transformed")
return null;
box.x += style.left;
box.y += style.top;
return box;
}
async scrollRectIntoViewIfNeeded(handle, rect) {
return await handle.evaluateInUtility(([injected, node]) => {
node.scrollIntoView({
block: "center",
inline: "center",
behavior: "instant"
});
}, null).then(() => "done").catch((e) => {
if (e instanceof Error && e.message.includes("Node is detached from document"))
return "error:notconnected";
if (e instanceof Error && e.message.includes("Node does not have a layout object"))
return "error:notvisible";
throw e;
});
}
async setScreencastOptions(options) {
}
rafCountForStablePosition() {
return 1;
}
async getContentQuads(handle) {
const quads = await handle.evaluateInUtility(([injected, node]) => {
if (!node.isConnected)
return "error:notconnected";
const rects = node.getClientRects();
if (!rects)
return null;
return [...rects].map((rect) => [
{ x: rect.left, y: rect.top },
{ x: rect.right, y: rect.top },
{ x: rect.right, y: rect.bottom },
{ x: rect.left, y: rect.bottom }
]);
}, null);
if (!quads || quads === "error:notconnected")
return quads;
const position = await this._framePosition(handle._frame);
if (!position)
return null;
quads.forEach((quad) => quad.forEach((point) => {
point.x += position.x;
point.y += position.y;
}));
return quads;
}
async setInputFilePaths(handle, paths) {
const fromContext = toBidiExecutionContext(handle._context);
await this._session.send("input.setFiles", {
context: this._session.sessionId,
element: await fromContext.nodeIdForElementHandle(handle),
files: paths
});
}
async adoptElementHandle(handle, to) {
const fromContext = toBidiExecutionContext(handle._context);
const nodeId = await fromContext.nodeIdForElementHandle(handle);
const executionContext = toBidiExecutionContext(to);
return await executionContext.remoteObjectForNodeId(to, nodeId);
}
async getAccessibilityTree(needle) {
throw new Error("Method not implemented.");
}
async inputActionEpilogue() {
}
async resetForReuse(progress) {
}
async pdf(options) {
return this._pdf.generate(options);
}
async getFrameElement(frame) {
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)
throw new Error("Frame has been detached.");
return foundElement;
}
shouldToggleStyleSheetToSyncAnimations() {
return true;
}
}
function toBidiExecutionContext(executionContext) {
return executionContext.delegate;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
BidiPage,
kPlaywrightBindingChannel
});

106
node_modules/playwright-core/lib/server/bidi/bidiPdf.js generated vendored Normal file
View File

@@ -0,0 +1,106 @@
"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 bidiPdf_exports = {};
__export(bidiPdf_exports, {
BidiPDF: () => BidiPDF
});
module.exports = __toCommonJS(bidiPdf_exports);
var import_utils = require("../../utils");
const PagePaperFormats = {
letter: { width: 8.5, height: 11 },
legal: { width: 8.5, height: 14 },
tabloid: { width: 11, height: 17 },
ledger: { width: 17, height: 11 },
a0: { width: 33.1, height: 46.8 },
a1: { width: 23.4, height: 33.1 },
a2: { width: 16.54, height: 23.4 },
a3: { width: 11.7, height: 16.54 },
a4: { width: 8.27, height: 11.7 },
a5: { width: 5.83, height: 8.27 },
a6: { width: 4.13, height: 5.83 }
};
const unitToPixels = {
"px": 1,
"in": 96,
"cm": 37.8,
"mm": 3.78
};
function convertPrintParameterToInches(text) {
if (text === void 0)
return void 0;
let unit = text.substring(text.length - 2).toLowerCase();
let valueText = "";
if (unitToPixels.hasOwnProperty(unit)) {
valueText = text.substring(0, text.length - 2);
} else {
unit = "px";
valueText = text;
}
const value = Number(valueText);
(0, import_utils.assert)(!isNaN(value), "Failed to parse parameter value: " + text);
const pixels = value * unitToPixels[unit];
return pixels / 96;
}
class BidiPDF {
constructor(session) {
this._session = session;
}
async generate(options) {
const {
scale = 1,
printBackground = false,
landscape = false,
pageRanges = "",
margin = {}
} = options;
let paperWidth = 8.5;
let paperHeight = 11;
if (options.format) {
const format = PagePaperFormats[options.format.toLowerCase()];
(0, import_utils.assert)(format, "Unknown paper format: " + options.format);
paperWidth = format.width;
paperHeight = format.height;
} else {
paperWidth = convertPrintParameterToInches(options.width) || paperWidth;
paperHeight = convertPrintParameterToInches(options.height) || paperHeight;
}
const { data } = await this._session.send("browsingContext.print", {
context: this._session.sessionId,
background: printBackground,
margin: {
bottom: convertPrintParameterToInches(margin.bottom) || 0,
left: convertPrintParameterToInches(margin.left) || 0,
right: convertPrintParameterToInches(margin.right) || 0,
top: convertPrintParameterToInches(margin.top) || 0
},
orientation: landscape ? "landscape" : "portrait",
page: {
width: paperWidth,
height: paperHeight
},
pageRanges: pageRanges ? pageRanges.split(",").map((r) => r.trim()) : void 0,
scale
});
return Buffer.from(data, "base64");
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
BidiPDF
});

View File

@@ -0,0 +1,22 @@
"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 bidiCommands_d_exports = {};
module.exports = __toCommonJS(bidiCommands_d_exports);
/**
* @license
* Copyright 2024 Google Inc.
* Modifications copyright (c) Microsoft Corporation.
* SPDX-License-Identifier: Apache-2.0
*/

View File

@@ -0,0 +1,98 @@
"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
});

View File

@@ -0,0 +1,256 @@
"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 bidiKeyboard_exports = {};
__export(bidiKeyboard_exports, {
getBidiKeyValue: () => getBidiKeyValue
});
module.exports = __toCommonJS(bidiKeyboard_exports);
/**
* @license
* Copyright 2024 Google Inc.
* Modifications copyright (c) Microsoft Corporation.
* SPDX-License-Identifier: Apache-2.0
*/
const getBidiKeyValue = (keyName) => {
switch (keyName) {
case "\r":
case "\n":
keyName = "Enter";
break;
}
if ([...keyName].length === 1) {
return keyName;
}
switch (keyName) {
case "Cancel":
return "\uE001";
case "Help":
return "\uE002";
case "Backspace":
return "\uE003";
case "Tab":
return "\uE004";
case "Clear":
return "\uE005";
case "Enter":
return "\uE007";
case "Shift":
case "ShiftLeft":
return "\uE008";
case "Control":
case "ControlLeft":
return "\uE009";
case "Alt":
case "AltLeft":
return "\uE00A";
case "Pause":
return "\uE00B";
case "Escape":
return "\uE00C";
case "PageUp":
return "\uE00E";
case "PageDown":
return "\uE00F";
case "End":
return "\uE010";
case "Home":
return "\uE011";
case "ArrowLeft":
return "\uE012";
case "ArrowUp":
return "\uE013";
case "ArrowRight":
return "\uE014";
case "ArrowDown":
return "\uE015";
case "Insert":
return "\uE016";
case "Delete":
return "\uE017";
case "NumpadEqual":
return "\uE019";
case "Numpad0":
return "\uE01A";
case "Numpad1":
return "\uE01B";
case "Numpad2":
return "\uE01C";
case "Numpad3":
return "\uE01D";
case "Numpad4":
return "\uE01E";
case "Numpad5":
return "\uE01F";
case "Numpad6":
return "\uE020";
case "Numpad7":
return "\uE021";
case "Numpad8":
return "\uE022";
case "Numpad9":
return "\uE023";
case "NumpadMultiply":
return "\uE024";
case "NumpadAdd":
return "\uE025";
case "NumpadSubtract":
return "\uE027";
case "NumpadDecimal":
return "\uE028";
case "NumpadDivide":
return "\uE029";
case "F1":
return "\uE031";
case "F2":
return "\uE032";
case "F3":
return "\uE033";
case "F4":
return "\uE034";
case "F5":
return "\uE035";
case "F6":
return "\uE036";
case "F7":
return "\uE037";
case "F8":
return "\uE038";
case "F9":
return "\uE039";
case "F10":
return "\uE03A";
case "F11":
return "\uE03B";
case "F12":
return "\uE03C";
case "Meta":
case "MetaLeft":
return "\uE03D";
case "ShiftRight":
return "\uE050";
case "ControlRight":
return "\uE051";
case "AltRight":
return "\uE052";
case "MetaRight":
return "\uE053";
case "Space":
return " ";
case "Digit0":
return "0";
case "Digit1":
return "1";
case "Digit2":
return "2";
case "Digit3":
return "3";
case "Digit4":
return "4";
case "Digit5":
return "5";
case "Digit6":
return "6";
case "Digit7":
return "7";
case "Digit8":
return "8";
case "Digit9":
return "9";
case "KeyA":
return "a";
case "KeyB":
return "b";
case "KeyC":
return "c";
case "KeyD":
return "d";
case "KeyE":
return "e";
case "KeyF":
return "f";
case "KeyG":
return "g";
case "KeyH":
return "h";
case "KeyI":
return "i";
case "KeyJ":
return "j";
case "KeyK":
return "k";
case "KeyL":
return "l";
case "KeyM":
return "m";
case "KeyN":
return "n";
case "KeyO":
return "o";
case "KeyP":
return "p";
case "KeyQ":
return "q";
case "KeyR":
return "r";
case "KeyS":
return "s";
case "KeyT":
return "t";
case "KeyU":
return "u";
case "KeyV":
return "v";
case "KeyW":
return "w";
case "KeyX":
return "x";
case "KeyY":
return "y";
case "KeyZ":
return "z";
case "Semicolon":
return ";";
case "Equal":
return "=";
case "Comma":
return ",";
case "Minus":
return "-";
case "Period":
return ".";
case "Slash":
return "/";
case "Backquote":
return "`";
case "BracketLeft":
return "[";
case "Backslash":
return "\\";
case "BracketRight":
return "]";
case "Quote":
return '"';
default:
throw new Error(`Unknown key: "${keyName}"`);
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
getBidiKeyValue
});

View File

@@ -0,0 +1,24 @@
"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 __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var bidiProtocol_exports = {};
module.exports = __toCommonJS(bidiProtocol_exports);
__reExport(bidiProtocol_exports, require("./bidiProtocolCore"), module.exports);
__reExport(bidiProtocol_exports, require("./bidiProtocolPermissions"), module.exports);
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
...require("./bidiProtocolCore"),
...require("./bidiProtocolPermissions")
});

View File

@@ -0,0 +1,179 @@
"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 bidiProtocolCore_exports = {};
__export(bidiProtocolCore_exports, {
BrowsingContext: () => BrowsingContext,
Emulation: () => Emulation,
ErrorCode: () => ErrorCode,
Input: () => Input,
Log: () => Log,
Network: () => Network,
Script: () => Script,
Session: () => Session
});
module.exports = __toCommonJS(bidiProtocolCore_exports);
var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
ErrorCode2["InvalidArgument"] = "invalid argument";
ErrorCode2["InvalidSelector"] = "invalid selector";
ErrorCode2["InvalidSessionId"] = "invalid session id";
ErrorCode2["InvalidWebExtension"] = "invalid web extension";
ErrorCode2["MoveTargetOutOfBounds"] = "move target out of bounds";
ErrorCode2["NoSuchAlert"] = "no such alert";
ErrorCode2["NoSuchNetworkCollector"] = "no such network collector";
ErrorCode2["NoSuchElement"] = "no such element";
ErrorCode2["NoSuchFrame"] = "no such frame";
ErrorCode2["NoSuchHandle"] = "no such handle";
ErrorCode2["NoSuchHistoryEntry"] = "no such history entry";
ErrorCode2["NoSuchIntercept"] = "no such intercept";
ErrorCode2["NoSuchNetworkData"] = "no such network data";
ErrorCode2["NoSuchNode"] = "no such node";
ErrorCode2["NoSuchRequest"] = "no such request";
ErrorCode2["NoSuchScript"] = "no such script";
ErrorCode2["NoSuchStoragePartition"] = "no such storage partition";
ErrorCode2["NoSuchUserContext"] = "no such user context";
ErrorCode2["NoSuchWebExtension"] = "no such web extension";
ErrorCode2["SessionNotCreated"] = "session not created";
ErrorCode2["UnableToCaptureScreen"] = "unable to capture screen";
ErrorCode2["UnableToCloseBrowser"] = "unable to close browser";
ErrorCode2["UnableToSetCookie"] = "unable to set cookie";
ErrorCode2["UnableToSetFileInput"] = "unable to set file input";
ErrorCode2["UnavailableNetworkData"] = "unavailable network data";
ErrorCode2["UnderspecifiedStoragePartition"] = "underspecified storage partition";
ErrorCode2["UnknownCommand"] = "unknown command";
ErrorCode2["UnknownError"] = "unknown error";
ErrorCode2["UnsupportedOperation"] = "unsupported operation";
return ErrorCode2;
})(ErrorCode || {});
var Session;
((Session2) => {
let UserPromptHandlerType;
((UserPromptHandlerType2) => {
UserPromptHandlerType2["Accept"] = "accept";
UserPromptHandlerType2["Dismiss"] = "dismiss";
UserPromptHandlerType2["Ignore"] = "ignore";
})(UserPromptHandlerType = Session2.UserPromptHandlerType || (Session2.UserPromptHandlerType = {}));
})(Session || (Session = {}));
var BrowsingContext;
((BrowsingContext2) => {
let ReadinessState;
((ReadinessState2) => {
ReadinessState2["None"] = "none";
ReadinessState2["Interactive"] = "interactive";
ReadinessState2["Complete"] = "complete";
})(ReadinessState = BrowsingContext2.ReadinessState || (BrowsingContext2.ReadinessState = {}));
})(BrowsingContext || (BrowsingContext = {}));
((BrowsingContext2) => {
let UserPromptType;
((UserPromptType2) => {
UserPromptType2["Alert"] = "alert";
UserPromptType2["Beforeunload"] = "beforeunload";
UserPromptType2["Confirm"] = "confirm";
UserPromptType2["Prompt"] = "prompt";
})(UserPromptType = BrowsingContext2.UserPromptType || (BrowsingContext2.UserPromptType = {}));
})(BrowsingContext || (BrowsingContext = {}));
((BrowsingContext2) => {
let CreateType;
((CreateType2) => {
CreateType2["Tab"] = "tab";
CreateType2["Window"] = "window";
})(CreateType = BrowsingContext2.CreateType || (BrowsingContext2.CreateType = {}));
})(BrowsingContext || (BrowsingContext = {}));
var Emulation;
((Emulation2) => {
let ForcedColorsModeTheme;
((ForcedColorsModeTheme2) => {
ForcedColorsModeTheme2["Light"] = "light";
ForcedColorsModeTheme2["Dark"] = "dark";
})(ForcedColorsModeTheme = Emulation2.ForcedColorsModeTheme || (Emulation2.ForcedColorsModeTheme = {}));
})(Emulation || (Emulation = {}));
((Emulation2) => {
let ScreenOrientationNatural;
((ScreenOrientationNatural2) => {
ScreenOrientationNatural2["Portrait"] = "portrait";
ScreenOrientationNatural2["Landscape"] = "landscape";
})(ScreenOrientationNatural = Emulation2.ScreenOrientationNatural || (Emulation2.ScreenOrientationNatural = {}));
})(Emulation || (Emulation = {}));
var Network;
((Network2) => {
let CollectorType;
((CollectorType2) => {
CollectorType2["Blob"] = "blob";
})(CollectorType = Network2.CollectorType || (Network2.CollectorType = {}));
})(Network || (Network = {}));
((Network2) => {
let SameSite;
((SameSite2) => {
SameSite2["Strict"] = "strict";
SameSite2["Lax"] = "lax";
SameSite2["None"] = "none";
SameSite2["Default"] = "default";
})(SameSite = Network2.SameSite || (Network2.SameSite = {}));
})(Network || (Network = {}));
((Network2) => {
let DataType;
((DataType2) => {
DataType2["Response"] = "response";
})(DataType = Network2.DataType || (Network2.DataType = {}));
})(Network || (Network = {}));
((Network2) => {
let InterceptPhase;
((InterceptPhase2) => {
InterceptPhase2["BeforeRequestSent"] = "beforeRequestSent";
InterceptPhase2["ResponseStarted"] = "responseStarted";
InterceptPhase2["AuthRequired"] = "authRequired";
})(InterceptPhase = Network2.InterceptPhase || (Network2.InterceptPhase = {}));
})(Network || (Network = {}));
var Script;
((Script2) => {
let ResultOwnership;
((ResultOwnership2) => {
ResultOwnership2["Root"] = "root";
ResultOwnership2["None"] = "none";
})(ResultOwnership = Script2.ResultOwnership || (Script2.ResultOwnership = {}));
})(Script || (Script = {}));
var Log;
((Log2) => {
let Level;
((Level2) => {
Level2["Debug"] = "debug";
Level2["Info"] = "info";
Level2["Warn"] = "warn";
Level2["Error"] = "error";
})(Level = Log2.Level || (Log2.Level = {}));
})(Log || (Log = {}));
var Input;
((Input2) => {
let PointerType;
((PointerType2) => {
PointerType2["Mouse"] = "mouse";
PointerType2["Pen"] = "pen";
PointerType2["Touch"] = "touch";
})(PointerType = Input2.PointerType || (Input2.PointerType = {}));
})(Input || (Input = {}));
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
BrowsingContext,
Emulation,
ErrorCode,
Input,
Log,
Network,
Script,
Session
});

View File

@@ -0,0 +1,42 @@
"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 bidiProtocolPermissions_exports = {};
__export(bidiProtocolPermissions_exports, {
Permissions: () => Permissions
});
module.exports = __toCommonJS(bidiProtocolPermissions_exports);
/**
* @license
* Copyright 2024 Google Inc.
* Modifications copyright (c) Microsoft Corporation.
* SPDX-License-Identifier: Apache-2.0
*/
var Permissions;
((Permissions2) => {
let PermissionState;
((PermissionState2) => {
PermissionState2["Granted"] = "granted";
PermissionState2["Denied"] = "denied";
PermissionState2["Prompt"] = "prompt";
})(PermissionState = Permissions2.PermissionState || (Permissions2.PermissionState = {}));
})(Permissions || (Permissions = {}));
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Permissions
});

View File

@@ -0,0 +1,148 @@
"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 bidiSerializer_exports = {};
__export(bidiSerializer_exports, {
BidiSerializer: () => BidiSerializer,
isDate: () => isDate,
isPlainObject: () => isPlainObject,
isRegExp: () => isRegExp
});
module.exports = __toCommonJS(bidiSerializer_exports);
/**
* @license
* Copyright 2024 Google Inc.
* Modifications copyright (c) Microsoft Corporation.
* SPDX-License-Identifier: Apache-2.0
*/
class UnserializableError extends Error {
}
class BidiSerializer {
static serialize(arg) {
switch (typeof arg) {
case "symbol":
case "function":
throw new UnserializableError(`Unable to serializable ${typeof arg}`);
case "object":
return BidiSerializer._serializeObject(arg);
case "undefined":
return {
type: "undefined"
};
case "number":
return BidiSerializer._serializeNumber(arg);
case "bigint":
return {
type: "bigint",
value: arg.toString()
};
case "string":
return {
type: "string",
value: arg
};
case "boolean":
return {
type: "boolean",
value: arg
};
}
}
static _serializeNumber(arg) {
let value;
if (Object.is(arg, -0)) {
value = "-0";
} else if (Object.is(arg, Infinity)) {
value = "Infinity";
} else if (Object.is(arg, -Infinity)) {
value = "-Infinity";
} else if (Object.is(arg, NaN)) {
value = "NaN";
} else {
value = arg;
}
return {
type: "number",
value
};
}
static _serializeObject(arg) {
if (arg === null) {
return {
type: "null"
};
} else if (Array.isArray(arg)) {
const parsedArray = arg.map((subArg) => {
return BidiSerializer.serialize(subArg);
});
return {
type: "array",
value: parsedArray
};
} else if (isPlainObject(arg)) {
try {
JSON.stringify(arg);
} catch (error) {
if (error instanceof TypeError && error.message.startsWith("Converting circular structure to JSON")) {
error.message += " Recursive objects are not allowed.";
}
throw error;
}
const parsedObject = [];
for (const key in arg) {
parsedObject.push([BidiSerializer.serialize(key), BidiSerializer.serialize(arg[key])]);
}
return {
type: "object",
value: parsedObject
};
} else if (isRegExp(arg)) {
return {
type: "regexp",
value: {
pattern: arg.source,
flags: arg.flags
}
};
} else if (isDate(arg)) {
return {
type: "date",
value: arg.toISOString()
};
}
throw new UnserializableError(
"Custom object serialization not possible. Use plain objects instead."
);
}
}
const isPlainObject = (obj) => {
return typeof obj === "object" && obj?.constructor === Object;
};
const isRegExp = (obj) => {
return typeof obj === "object" && obj?.constructor === RegExp;
};
const isDate = (obj) => {
return typeof obj === "object" && obj?.constructor === Date;
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
BidiSerializer,
isDate,
isPlainObject,
isRegExp
});

View File

@@ -0,0 +1,259 @@
"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 firefoxPrefs_exports = {};
__export(firefoxPrefs_exports, {
createProfile: () => createProfile
});
module.exports = __toCommonJS(firefoxPrefs_exports);
var import_fs = __toESM(require("fs"));
var import_path = __toESM(require("path"));
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
async function createProfile(options) {
if (!import_fs.default.existsSync(options.path)) {
await import_fs.default.promises.mkdir(options.path, {
recursive: true
});
}
await writePreferences({
preferences: {
...defaultProfilePreferences(options.preferences),
...options.preferences
},
path: options.path
});
}
function defaultProfilePreferences(extraPrefs) {
const server = "dummy.test";
const defaultPrefs = {
// Make sure Shield doesn't hit the network.
"app.normandy.api_url": "",
// Disable Firefox old build background check
"app.update.checkInstallTime": false,
// Disable automatically upgrading Firefox
"app.update.disabledForTesting": true,
// Increase the APZ content response timeout to 1 minute
"apz.content_response_timeout": 6e4,
// Prevent various error message on the console
// jest-puppeteer asserts that no error message is emitted by the console
"browser.contentblocking.features.standard": "-tp,tpPrivate,cookieBehavior0,-cm,-fp",
// Enable the dump function: which sends messages to the system
// console
// https://bugzilla.mozilla.org/show_bug.cgi?id=1543115
"browser.dom.window.dump.enabled": true,
// Make sure newtab weather doesn't hit the network to retrieve weather data.
"browser.newtabpage.activity-stream.discoverystream.region-weather-config": "",
// Make sure newtab wallpapers don't hit the network to retrieve wallpaper data.
"browser.newtabpage.activity-stream.newtabWallpapers.enabled": false,
"browser.newtabpage.activity-stream.newtabWallpapers.v2.enabled": false,
// Make sure Topsites doesn't hit the network to retrieve sponsored tiles.
"browser.newtabpage.activity-stream.showSponsoredTopSites": false,
// Disable topstories
"browser.newtabpage.activity-stream.feeds.system.topstories": false,
// Always display a blank page
"browser.newtabpage.enabled": false,
// Background thumbnails in particular cause grief: and disabling
// thumbnails in general cannot hurt
"browser.pagethumbnails.capturing_disabled": true,
// Disable safebrowsing components.
"browser.safebrowsing.blockedURIs.enabled": false,
"browser.safebrowsing.downloads.enabled": false,
"browser.safebrowsing.malware.enabled": false,
"browser.safebrowsing.phishing.enabled": false,
// Disable updates to search engines.
"browser.search.update": false,
// Do not restore the last open set of tabs if the browser has crashed
"browser.sessionstore.resume_from_crash": false,
// Skip check for default browser on startup
"browser.shell.checkDefaultBrowser": false,
// Disable newtabpage
"browser.startup.homepage": "about:blank",
// Do not redirect user when a milstone upgrade of Firefox is detected
"browser.startup.homepage_override.mstone": "ignore",
// Start with a blank page about:blank
"browser.startup.page": 0,
// Do not allow background tabs to be zombified on Android: otherwise for
// tests that open additional tabs: the test harness tab itself might get
// unloaded
"browser.tabs.disableBackgroundZombification": false,
// Do not warn when closing all other open tabs
"browser.tabs.warnOnCloseOtherTabs": false,
// Do not warn when multiple tabs will be opened
"browser.tabs.warnOnOpen": false,
// Do not automatically offer translations, as tests do not expect this.
"browser.translations.automaticallyPopup": false,
// Disable the UI tour.
"browser.uitour.enabled": false,
// Turn off search suggestions in the location bar so as not to trigger
// network connections.
"browser.urlbar.suggest.searches": false,
// Disable first run splash page on Windows 10
"browser.usedOnWindows10.introURL": "",
// Do not warn on quitting Firefox
"browser.warnOnQuit": false,
// Defensively disable data reporting systems
"datareporting.healthreport.documentServerURI": `http://${server}/dummy/healthreport/`,
"datareporting.healthreport.logging.consoleEnabled": false,
"datareporting.healthreport.service.enabled": false,
"datareporting.healthreport.service.firstRun": false,
"datareporting.healthreport.uploadEnabled": false,
// Do not show datareporting policy notifications which can interfere with tests
"datareporting.policy.dataSubmissionEnabled": false,
"datareporting.policy.dataSubmissionPolicyBypassNotification": true,
// DevTools JSONViewer sometimes fails to load dependencies with its require.js.
// This doesn't affect Puppeteer but spams console (Bug 1424372)
"devtools.jsonview.enabled": false,
// Disable popup-blocker
"dom.disable_open_during_load": false,
// Enable the support for File object creation in the content process
// Required for |Page.setFileInputFiles| protocol method.
"dom.file.createInChild": true,
// Disable the ProcessHangMonitor
"dom.ipc.reportProcessHangs": false,
// Disable slow script dialogues
"dom.max_chrome_script_run_time": 0,
"dom.max_script_run_time": 0,
// Disable background timer throttling to allow tests to run in parallel
// without a decrease in performance.
"dom.min_background_timeout_value": 0,
"dom.min_background_timeout_value_without_budget_throttling": 0,
"dom.timeout.enable_budget_timer_throttling": false,
// Disable HTTPS-First upgrades
"dom.security.https_first": false,
// Only load extensions from the application and user profile
// AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION
"extensions.autoDisableScopes": 0,
"extensions.enabledScopes": 5,
// Disable metadata caching for installed add-ons by default
"extensions.getAddons.cache.enabled": false,
// Disable installing any distribution extensions or add-ons.
"extensions.installDistroAddons": false,
// Disabled screenshots extension
"extensions.screenshots.disabled": true,
// Turn off extension updates so they do not bother tests
"extensions.update.enabled": false,
// Turn off extension updates so they do not bother tests
"extensions.update.notifyUser": false,
// Make sure opening about:addons will not hit the network
"extensions.webservice.discoverURL": `http://${server}/dummy/discoveryURL`,
// Allow the application to have focus even it runs in the background
"focusmanager.testmode": true,
// Disable useragent updates
"general.useragent.updates.enabled": false,
// Always use network provider for geolocation tests so we bypass the
// macOS dialog raised by the corelocation provider
"geo.provider.testing": true,
// Do not scan Wifi
"geo.wifi.scan": false,
// No hang monitor
"hangmonitor.timeout": 0,
// Show chrome errors and warnings in the error console
"javascript.options.showInConsole": true,
// Do not throttle rendering (requestAnimationFrame) in background tabs
"layout.testing.top-level-always-active": true,
// Disable download and usage of OpenH264: and Widevine plugins
"media.gmp-manager.updateEnabled": false,
// Disable the GFX sanity window
"media.sanity-test.disabled": true,
// Disable connectivity service pings
"network.connectivity-service.enabled": false,
// Disable experimental feature that is only available in Nightly
"network.cookie.sameSite.laxByDefault": false,
// Do not prompt for temporary redirects
"network.http.prompt-temp-redirect": false,
// Disable speculative connections so they are not reported as leaking
// when they are hanging around
"network.http.speculative-parallel-limit": 0,
// Do not automatically switch between offline and online
"network.manage-offline-status": false,
// Make sure SNTP requests do not hit the network
"network.sntp.pools": server,
// Disable Flash.
"plugin.state.flash": 0,
"privacy.trackingprotection.enabled": false,
// Can be removed once Firefox 89 is no longer supported
// https://bugzilla.mozilla.org/show_bug.cgi?id=1710839
"remote.enabled": true,
// Don't do network connections for mitm priming
"security.certerrors.mitm.priming.enabled": false,
// Local documents have access to all other local documents,
// including directory listings
"security.fileuri.strict_origin_policy": false,
// Do not wait for the notification button security delay
"security.notification_enable_delay": 0,
// Do not automatically fill sign-in forms with known usernames and
// passwords
"signon.autofillForms": false,
// Disable password capture, so that tests that include forms are not
// influenced by the presence of the persistent doorhanger notification
"signon.rememberSignons": false,
// Disable first-run welcome page
"startup.homepage_welcome_url": "about:blank",
// Disable first-run welcome page
"startup.homepage_welcome_url.additional": "",
// Disable browser animations (tabs, fullscreen, sliding alerts)
"toolkit.cosmeticAnimations.enabled": false,
// Prevent starting into safe mode after application crashes
"toolkit.startup.max_resumed_crashes": -1
};
return Object.assign(defaultPrefs, extraPrefs);
}
async function writePreferences(options) {
const prefsPath = import_path.default.join(options.path, "prefs.js");
const lines = Object.entries(options.preferences).map(([key, value]) => {
return `user_pref(${JSON.stringify(key)}, ${JSON.stringify(value)});`;
});
const result = await Promise.allSettled([
import_fs.default.promises.writeFile(import_path.default.join(options.path, "user.js"), lines.join("\n")),
// Create a backup of the preferences file if it already exitsts.
import_fs.default.promises.access(prefsPath, import_fs.default.constants.F_OK).then(
async () => {
await import_fs.default.promises.copyFile(
prefsPath,
import_path.default.join(options.path, "prefs.js.playwright")
);
},
// Swallow only if file does not exist
() => {
}
)
]);
for (const command of result) {
if (command.status === "rejected") {
throw command.reason;
}
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
createProfile
});