puppeteer-core
Version:
A high-level API to control headless Chrome over the DevTools Protocol
743 lines • 29.8 kB
JavaScript
"use strict";
/**
* Copyright 2022 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
if (value !== null && value !== void 0) {
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
var dispose;
if (async) {
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
dispose = value[Symbol.asyncDispose];
}
if (dispose === void 0) {
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
dispose = value[Symbol.dispose];
}
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
env.stack.push({ value: value, dispose: dispose, async: async });
}
else if (async) {
env.stack.push({ async: true });
}
return value;
};
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
return function (env) {
function fail(e) {
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
env.hasError = true;
}
function next() {
while (env.stack.length) {
var rec = env.stack.pop();
try {
var result = rec.dispose && rec.dispose.call(rec.value);
if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
}
catch (e) {
fail(e);
}
}
if (env.hasError) throw env.error;
}
return next();
};
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
});
Object.defineProperty(exports, "__esModule", { value: true });
exports.BidiPage = void 0;
const rxjs_js_1 = require("../../third_party/rxjs/rxjs.js");
const Page_js_1 = require("../api/Page.js");
const Accessibility_js_1 = require("../cdp/Accessibility.js");
const Coverage_js_1 = require("../cdp/Coverage.js");
const EmulationManager_js_1 = require("../cdp/EmulationManager.js");
const FrameTree_js_1 = require("../cdp/FrameTree.js");
const Tracing_js_1 = require("../cdp/Tracing.js");
const ConsoleMessage_js_1 = require("../common/ConsoleMessage.js");
const Errors_js_1 = require("../common/Errors.js");
const NetworkManagerEvents_js_1 = require("../common/NetworkManagerEvents.js");
const util_js_1 = require("../common/util.js");
const assert_js_1 = require("../util/assert.js");
const Deferred_js_1 = require("../util/Deferred.js");
const disposable_js_1 = require("../util/disposable.js");
const ErrorLike_js_1 = require("../util/ErrorLike.js");
const BrowsingContext_js_1 = require("./BrowsingContext.js");
const Deserializer_js_1 = require("./Deserializer.js");
const Dialog_js_1 = require("./Dialog.js");
const ElementHandle_js_1 = require("./ElementHandle.js");
const EmulationManager_js_2 = require("./EmulationManager.js");
const Frame_js_1 = require("./Frame.js");
const Input_js_1 = require("./Input.js");
const lifecycle_js_1 = require("./lifecycle.js");
const NetworkManager_js_1 = require("./NetworkManager.js");
const Realm_js_1 = require("./Realm.js");
/**
* @internal
*/
class BidiPage extends Page_js_1.Page {
#accessibility;
#connection;
#frameTree = new FrameTree_js_1.FrameTree();
#networkManager;
#viewport = null;
#closedDeferred = Deferred_js_1.Deferred.create();
#subscribedEvents = new Map([
['log.entryAdded', this.#onLogEntryAdded.bind(this)],
['browsingContext.load', this.#onFrameLoaded.bind(this)],
[
'browsingContext.fragmentNavigated',
this.#onFrameFragmentNavigated.bind(this),
],
[
'browsingContext.domContentLoaded',
this.#onFrameDOMContentLoaded.bind(this),
],
['browsingContext.userPromptOpened', this.#onDialog.bind(this)],
]);
#networkManagerEvents = [
[
NetworkManagerEvents_js_1.NetworkManagerEvent.Request,
(request) => {
this.emit("request" /* PageEvent.Request */, request);
},
],
[
NetworkManagerEvents_js_1.NetworkManagerEvent.RequestServedFromCache,
(request) => {
this.emit("requestservedfromcache" /* PageEvent.RequestServedFromCache */, request);
},
],
[
NetworkManagerEvents_js_1.NetworkManagerEvent.RequestFailed,
(request) => {
this.emit("requestfailed" /* PageEvent.RequestFailed */, request);
},
],
[
NetworkManagerEvents_js_1.NetworkManagerEvent.RequestFinished,
(request) => {
this.emit("requestfinished" /* PageEvent.RequestFinished */, request);
},
],
[
NetworkManagerEvents_js_1.NetworkManagerEvent.Response,
(response) => {
this.emit("response" /* PageEvent.Response */, response);
},
],
];
#browsingContextEvents = new Map([
[BrowsingContext_js_1.BrowsingContextEvent.Created, this.#onContextCreated.bind(this)],
[BrowsingContext_js_1.BrowsingContextEvent.Destroyed, this.#onContextDestroyed.bind(this)],
]);
#tracing;
#coverage;
#cdpEmulationManager;
#emulationManager;
#mouse;
#touchscreen;
#keyboard;
#browsingContext;
#browserContext;
#target;
_client() {
return this.mainFrame().context().cdpSession;
}
constructor(browsingContext, browserContext, target) {
super();
this.#browsingContext = browsingContext;
this.#browserContext = browserContext;
this.#target = target;
this.#connection = browsingContext.connection;
for (const [event, subscriber] of this.#browsingContextEvents) {
this.#browsingContext.on(event, subscriber);
}
this.#networkManager = new NetworkManager_js_1.BidiNetworkManager(this.#connection, this);
for (const [event, subscriber] of this.#subscribedEvents) {
this.#connection.on(event, subscriber);
}
for (const [event, subscriber] of this.#networkManagerEvents) {
// TODO: remove any
this.#networkManager.on(event, subscriber);
}
const frame = new Frame_js_1.BidiFrame(this, this.#browsingContext, this._timeoutSettings, this.#browsingContext.parent);
this.#frameTree.addFrame(frame);
this.emit("frameattached" /* PageEvent.FrameAttached */, frame);
// TODO: https://github.com/w3c/webdriver-bidi/issues/443
this.#accessibility = new Accessibility_js_1.Accessibility(this.mainFrame().context().cdpSession);
this.#tracing = new Tracing_js_1.Tracing(this.mainFrame().context().cdpSession);
this.#coverage = new Coverage_js_1.Coverage(this.mainFrame().context().cdpSession);
this.#cdpEmulationManager = new EmulationManager_js_1.EmulationManager(this.mainFrame().context().cdpSession);
this.#emulationManager = new EmulationManager_js_2.EmulationManager(browsingContext);
this.#mouse = new Input_js_1.BidiMouse(this.mainFrame().context());
this.#touchscreen = new Input_js_1.BidiTouchscreen(this.mainFrame().context());
this.#keyboard = new Input_js_1.BidiKeyboard(this);
}
/**
* @internal
*/
get connection() {
return this.#connection;
}
async setUserAgent(userAgent, userAgentMetadata) {
// TODO: handle CDP-specific cases such as mprach.
await this._client().send('Network.setUserAgentOverride', {
userAgent: userAgent,
userAgentMetadata: userAgentMetadata,
});
}
async setBypassCSP(enabled) {
// TODO: handle CDP-specific cases such as mprach.
await this._client().send('Page.setBypassCSP', { enabled });
}
async queryObjects(prototypeHandle) {
(0, assert_js_1.assert)(!prototypeHandle.disposed, 'Prototype JSHandle is disposed!');
(0, assert_js_1.assert)(prototypeHandle.id, 'Prototype JSHandle must not be referencing primitive value');
const response = await this.mainFrame().client.send('Runtime.queryObjects', {
prototypeObjectId: prototypeHandle.id,
});
return (0, Realm_js_1.createBidiHandle)(this.mainFrame().mainRealm(), {
type: 'array',
handle: response.objects.objectId,
});
}
_setBrowserContext(browserContext) {
this.#browserContext = browserContext;
}
get accessibility() {
return this.#accessibility;
}
get tracing() {
return this.#tracing;
}
get coverage() {
return this.#coverage;
}
get mouse() {
return this.#mouse;
}
get touchscreen() {
return this.#touchscreen;
}
get keyboard() {
return this.#keyboard;
}
browser() {
return this.browserContext().browser();
}
browserContext() {
return this.#browserContext;
}
mainFrame() {
const mainFrame = this.#frameTree.getMainFrame();
(0, assert_js_1.assert)(mainFrame, 'Requesting main frame too early!');
return mainFrame;
}
/**
* @internal
*/
async focusedFrame() {
const env_1 = { stack: [], error: void 0, hasError: false };
try {
const frame = __addDisposableResource(env_1, await this.mainFrame()
.isolatedRealm()
.evaluateHandle(() => {
let frame;
let win = window;
while (win?.document.activeElement instanceof HTMLIFrameElement) {
frame = win.document.activeElement;
win = frame.contentWindow;
}
return frame;
}), false);
if (!(frame instanceof ElementHandle_js_1.BidiElementHandle)) {
return this.mainFrame();
}
return await frame.contentFrame();
}
catch (e_1) {
env_1.error = e_1;
env_1.hasError = true;
}
finally {
__disposeResources(env_1);
}
}
frames() {
return Array.from(this.#frameTree.frames());
}
frame(frameId) {
return this.#frameTree.getById(frameId ?? '') || null;
}
childFrames(frameId) {
return this.#frameTree.childFrames(frameId);
}
#onFrameLoaded(info) {
const frame = this.frame(info.context);
if (frame && this.mainFrame() === frame) {
this.emit("load" /* PageEvent.Load */, undefined);
}
}
#onFrameFragmentNavigated(info) {
const frame = this.frame(info.context);
if (frame) {
this.emit("framenavigated" /* PageEvent.FrameNavigated */, frame);
}
}
#onFrameDOMContentLoaded(info) {
const frame = this.frame(info.context);
if (frame) {
frame._hasStartedLoading = true;
if (this.mainFrame() === frame) {
this.emit("domcontentloaded" /* PageEvent.DOMContentLoaded */, undefined);
}
this.emit("framenavigated" /* PageEvent.FrameNavigated */, frame);
}
}
#onContextCreated(context) {
if (!this.frame(context.id) &&
(this.frame(context.parent ?? '') || !this.#frameTree.getMainFrame())) {
const frame = new Frame_js_1.BidiFrame(this, context, this._timeoutSettings, context.parent);
this.#frameTree.addFrame(frame);
if (frame !== this.mainFrame()) {
this.emit("frameattached" /* PageEvent.FrameAttached */, frame);
}
}
}
#onContextDestroyed(context) {
const frame = this.frame(context.id);
if (frame) {
if (frame === this.mainFrame()) {
this.emit("close" /* PageEvent.Close */, undefined);
}
this.#removeFramesRecursively(frame);
}
}
#removeFramesRecursively(frame) {
for (const child of frame.childFrames()) {
this.#removeFramesRecursively(child);
}
frame[disposable_js_1.disposeSymbol]();
this.#networkManager.clearMapAfterFrameDispose(frame);
this.#frameTree.removeFrame(frame);
this.emit("framedetached" /* PageEvent.FrameDetached */, frame);
}
#onLogEntryAdded(event) {
const frame = this.frame(event.source.context);
if (!frame) {
return;
}
if (isConsoleLogEntry(event)) {
const args = event.args.map(arg => {
return (0, Realm_js_1.createBidiHandle)(frame.mainRealm(), arg);
});
const text = args
.reduce((value, arg) => {
const parsedValue = arg.isPrimitiveValue
? Deserializer_js_1.BidiDeserializer.deserialize(arg.remoteValue())
: arg.toString();
return `${value} ${parsedValue}`;
}, '')
.slice(1);
this.emit("console" /* PageEvent.Console */, new ConsoleMessage_js_1.ConsoleMessage(event.method, text, args, getStackTraceLocations(event.stackTrace)));
}
else if (isJavaScriptLogEntry(event)) {
const error = new Error(event.text ?? '');
const messageHeight = error.message.split('\n').length;
const messageLines = error.stack.split('\n').splice(0, messageHeight);
const stackLines = [];
if (event.stackTrace) {
for (const frame of event.stackTrace.callFrames) {
// Note we need to add `1` because the values are 0-indexed.
stackLines.push(` at ${frame.functionName || '<anonymous>'} (${frame.url}:${frame.lineNumber + 1}:${frame.columnNumber + 1})`);
if (stackLines.length >= Error.stackTraceLimit) {
break;
}
}
}
error.stack = [...messageLines, ...stackLines].join('\n');
this.emit("pageerror" /* PageEvent.PageError */, error);
}
else {
(0, util_js_1.debugError)(`Unhandled LogEntry with type "${event.type}", text "${event.text}" and level "${event.level}"`);
}
}
#onDialog(event) {
const frame = this.frame(event.context);
if (!frame) {
return;
}
const type = (0, util_js_1.validateDialogType)(event.type);
const dialog = new Dialog_js_1.BidiDialog(frame.context(), type, event.message, event.defaultValue);
this.emit("dialog" /* PageEvent.Dialog */, dialog);
}
getNavigationResponse(id) {
return this.#networkManager.getNavigationResponse(id);
}
isClosed() {
return this.#closedDeferred.finished();
}
async close(options) {
if (this.#closedDeferred.finished()) {
return;
}
this.#closedDeferred.reject(new Errors_js_1.TargetCloseError('Page closed!'));
this.#networkManager.dispose();
await this.#connection.send('browsingContext.close', {
context: this.mainFrame()._id,
promptUnload: options?.runBeforeUnload ?? false,
});
this.emit("close" /* PageEvent.Close */, undefined);
this.removeAllListeners();
}
async reload(options = {}) {
const { waitUntil = 'load', timeout: ms = this._timeoutSettings.navigationTimeout(), } = options;
const [readiness, networkIdle] = (0, lifecycle_js_1.getBiDiReadinessState)(waitUntil);
const response = await (0, rxjs_js_1.firstValueFrom)(this._waitWithNetworkIdle(this.#connection.send('browsingContext.reload', {
context: this.mainFrame()._id,
wait: readiness,
}), networkIdle)
.pipe((0, rxjs_js_1.raceWith)((0, util_js_1.timeout)(ms), (0, rxjs_js_1.from)(this.#closedDeferred.valueOrThrow())))
.pipe((0, lifecycle_js_1.rewriteNavigationError)(this.url(), ms)));
return this.getNavigationResponse(response?.result.navigation);
}
setDefaultNavigationTimeout(timeout) {
this._timeoutSettings.setDefaultNavigationTimeout(timeout);
}
setDefaultTimeout(timeout) {
this._timeoutSettings.setDefaultTimeout(timeout);
}
getDefaultTimeout() {
return this._timeoutSettings.timeout();
}
isJavaScriptEnabled() {
return this.#cdpEmulationManager.javascriptEnabled;
}
async setGeolocation(options) {
return await this.#cdpEmulationManager.setGeolocation(options);
}
async setJavaScriptEnabled(enabled) {
return await this.#cdpEmulationManager.setJavaScriptEnabled(enabled);
}
async emulateMediaType(type) {
return await this.#cdpEmulationManager.emulateMediaType(type);
}
async emulateCPUThrottling(factor) {
return await this.#cdpEmulationManager.emulateCPUThrottling(factor);
}
async emulateMediaFeatures(features) {
return await this.#cdpEmulationManager.emulateMediaFeatures(features);
}
async emulateTimezone(timezoneId) {
return await this.#cdpEmulationManager.emulateTimezone(timezoneId);
}
async emulateIdleState(overrides) {
return await this.#cdpEmulationManager.emulateIdleState(overrides);
}
async emulateVisionDeficiency(type) {
return await this.#cdpEmulationManager.emulateVisionDeficiency(type);
}
async setViewport(viewport) {
if (!this.#browsingContext.supportsCdp()) {
await this.#emulationManager.emulateViewport(viewport);
this.#viewport = viewport;
return;
}
const needsReload = await this.#cdpEmulationManager.emulateViewport(viewport);
this.#viewport = viewport;
if (needsReload) {
await this.reload();
}
}
viewport() {
return this.#viewport;
}
async pdf(options = {}) {
const { path = undefined } = options;
const { printBackground: background, margin, landscape, width, height, pageRanges: ranges, scale, preferCSSPageSize, timeout: ms, } = this._getPDFOptions(options, 'cm');
const pageRanges = ranges ? ranges.split(', ') : [];
const { result } = await (0, rxjs_js_1.firstValueFrom)((0, rxjs_js_1.from)(this.#connection.send('browsingContext.print', {
context: this.mainFrame()._id,
background,
margin,
orientation: landscape ? 'landscape' : 'portrait',
page: {
width,
height,
},
pageRanges,
scale,
shrinkToFit: !preferCSSPageSize,
})).pipe((0, rxjs_js_1.raceWith)((0, util_js_1.timeout)(ms))));
const buffer = Buffer.from(result.data, 'base64');
await this._maybeWriteBufferToFile(path, buffer);
return buffer;
}
async createPDFStream(options) {
const buffer = await this.pdf(options);
try {
const { Readable } = await Promise.resolve().then(() => __importStar(require('stream')));
return Readable.from(buffer);
}
catch (error) {
if (error instanceof TypeError) {
throw new Error('Can only pass a file path in a Node-like environment.');
}
throw error;
}
}
async _screenshot(options) {
const { clip, type, captureBeyondViewport, quality } = options;
if (options.omitBackground !== undefined && options.omitBackground) {
throw new Errors_js_1.UnsupportedOperation(`BiDi does not support 'omitBackground'.`);
}
if (options.optimizeForSpeed !== undefined && options.optimizeForSpeed) {
throw new Errors_js_1.UnsupportedOperation(`BiDi does not support 'optimizeForSpeed'.`);
}
if (options.fromSurface !== undefined && !options.fromSurface) {
throw new Errors_js_1.UnsupportedOperation(`BiDi does not support 'fromSurface'.`);
}
if (clip !== undefined && clip.scale !== undefined && clip.scale !== 1) {
throw new Errors_js_1.UnsupportedOperation(`BiDi does not support 'scale' in 'clip'.`);
}
let box;
if (clip) {
if (captureBeyondViewport) {
box = clip;
}
else {
// The clip is always with respect to the document coordinates, so we
// need to convert this to viewport coordinates when we aren't capturing
// beyond the viewport.
const [pageLeft, pageTop] = await this.evaluate(() => {
if (!window.visualViewport) {
throw new Error('window.visualViewport is not supported.');
}
return [
window.visualViewport.pageLeft,
window.visualViewport.pageTop,
];
});
box = {
...clip,
x: clip.x - pageLeft,
y: clip.y - pageTop,
};
}
}
const { result: { data }, } = await this.#connection.send('browsingContext.captureScreenshot', {
context: this.mainFrame()._id,
origin: captureBeyondViewport ? 'document' : 'viewport',
format: {
type: `image/${type}`,
...(quality !== undefined ? { quality: quality / 100 } : {}),
},
...(box ? { clip: { type: 'box', ...box } } : {}),
});
return data;
}
async waitForRequest(urlOrPredicate, options = {}) {
const { timeout = this._timeoutSettings.timeout() } = options;
return await (0, util_js_1.waitForHTTP)(this.#networkManager, NetworkManagerEvents_js_1.NetworkManagerEvent.Request, urlOrPredicate, timeout, this.#closedDeferred);
}
async waitForResponse(urlOrPredicate, options = {}) {
const { timeout = this._timeoutSettings.timeout() } = options;
return await (0, util_js_1.waitForHTTP)(this.#networkManager, NetworkManagerEvents_js_1.NetworkManagerEvent.Response, urlOrPredicate, timeout, this.#closedDeferred);
}
async waitForNetworkIdle(options = {}) {
const { idleTime = util_js_1.NETWORK_IDLE_TIME, timeout: ms = this._timeoutSettings.timeout(), } = options;
await (0, rxjs_js_1.firstValueFrom)(this._waitForNetworkIdle(this.#networkManager, idleTime).pipe((0, rxjs_js_1.raceWith)((0, util_js_1.timeout)(ms), (0, rxjs_js_1.from)(this.#closedDeferred.valueOrThrow()))));
}
/** @internal */
_waitWithNetworkIdle(observableInput, networkIdle) {
const delay = networkIdle
? this._waitForNetworkIdle(this.#networkManager, util_js_1.NETWORK_IDLE_TIME, networkIdle === 'networkidle0' ? 0 : 2)
: (0, rxjs_js_1.from)(Promise.resolve());
return (0, rxjs_js_1.forkJoin)([
(0, rxjs_js_1.from)(observableInput).pipe((0, rxjs_js_1.first)()),
delay.pipe((0, rxjs_js_1.first)()),
]).pipe((0, rxjs_js_1.map)(([response]) => {
return response;
}));
}
async createCDPSession() {
const { sessionId } = await this.mainFrame()
.context()
.cdpSession.send('Target.attachToTarget', {
targetId: this.mainFrame()._id,
flatten: true,
});
return new BrowsingContext_js_1.CdpSessionWrapper(this.mainFrame().context(), sessionId);
}
async bringToFront() {
await this.#connection.send('browsingContext.activate', {
context: this.mainFrame()._id,
});
}
async evaluateOnNewDocument(pageFunction, ...args) {
const expression = evaluationExpression(pageFunction, ...args);
const { result } = await this.#connection.send('script.addPreloadScript', {
functionDeclaration: expression,
contexts: [this.mainFrame()._id],
});
return { identifier: result.script };
}
async removeScriptToEvaluateOnNewDocument(id) {
await this.#connection.send('script.removePreloadScript', {
script: id,
});
}
async exposeFunction(name, pptrFunction) {
return await this.mainFrame().exposeFunction(name, 'default' in pptrFunction ? pptrFunction.default : pptrFunction);
}
isDragInterceptionEnabled() {
return false;
}
async setCacheEnabled(enabled) {
// TODO: handle CDP-specific cases such as mprach.
await this._client().send('Network.setCacheDisabled', {
cacheDisabled: !enabled,
});
}
isServiceWorkerBypassed() {
throw new Errors_js_1.UnsupportedOperation();
}
target() {
return this.#target;
}
waitForFileChooser() {
throw new Errors_js_1.UnsupportedOperation();
}
workers() {
throw new Errors_js_1.UnsupportedOperation();
}
setRequestInterception() {
throw new Errors_js_1.UnsupportedOperation();
}
setDragInterception() {
throw new Errors_js_1.UnsupportedOperation();
}
setBypassServiceWorker() {
throw new Errors_js_1.UnsupportedOperation();
}
setOfflineMode() {
throw new Errors_js_1.UnsupportedOperation();
}
emulateNetworkConditions() {
throw new Errors_js_1.UnsupportedOperation();
}
cookies() {
throw new Errors_js_1.UnsupportedOperation();
}
setCookie() {
throw new Errors_js_1.UnsupportedOperation();
}
deleteCookie() {
throw new Errors_js_1.UnsupportedOperation();
}
removeExposedFunction() {
// TODO: Quick win?
throw new Errors_js_1.UnsupportedOperation();
}
authenticate() {
throw new Errors_js_1.UnsupportedOperation();
}
setExtraHTTPHeaders() {
throw new Errors_js_1.UnsupportedOperation();
}
metrics() {
throw new Errors_js_1.UnsupportedOperation();
}
async goBack(options = {}) {
return await this.#go(-1, options);
}
async goForward(options = {}) {
return await this.#go(+1, options);
}
async #go(delta, options) {
try {
const result = await Promise.all([
this.waitForNavigation(options),
this.#connection.send('browsingContext.traverseHistory', {
delta,
context: this.mainFrame()._id,
}),
]);
return result[0];
}
catch (err) {
// TODO: waitForNavigation should be cancelled if an error happens.
if ((0, ErrorLike_js_1.isErrorLike)(err)) {
if (err.message.includes('no such history entry')) {
return null;
}
}
throw err;
}
}
waitForDevicePrompt() {
throw new Errors_js_1.UnsupportedOperation();
}
}
exports.BidiPage = BidiPage;
function isConsoleLogEntry(event) {
return event.type === 'console';
}
function isJavaScriptLogEntry(event) {
return event.type === 'javascript';
}
function getStackTraceLocations(stackTrace) {
const stackTraceLocations = [];
if (stackTrace) {
for (const callFrame of stackTrace.callFrames) {
stackTraceLocations.push({
url: callFrame.url,
lineNumber: callFrame.lineNumber,
columnNumber: callFrame.columnNumber,
});
}
}
return stackTraceLocations;
}
function evaluationExpression(fun, ...args) {
return `() => {${(0, util_js_1.evaluationString)(fun, ...args)}}`;
}
//# sourceMappingURL=Page.js.map