Add .gitignore to exclude all node packages and lock files
This commit is contained in:
Generated
Vendored
+97
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
import { BrowserLog } from '../browser-log';
|
||||
import type { LogLevel } from '../log-level';
|
||||
import type { OnLog, Page } from './BrowserPage';
|
||||
import type { BrowserRunner } from './BrowserRunner';
|
||||
import type { Connection } from './Connection';
|
||||
import { EventEmitter } from './EventEmitter';
|
||||
import type { Viewport } from './PuppeteerViewport';
|
||||
import type { SourceMapGetter } from './source-map-getter';
|
||||
import { Target } from './Target';
|
||||
interface WaitForTargetOptions {
|
||||
timeout?: number;
|
||||
}
|
||||
export declare const enum BrowserEmittedEvents {
|
||||
TargetChanged = "targetchanged",
|
||||
TargetCreated = "targetcreated",
|
||||
Closed = "closed",
|
||||
ClosedSilent = "closed-silent"
|
||||
}
|
||||
export declare class HeadlessBrowser extends EventEmitter {
|
||||
#private;
|
||||
static create({ defaultViewport, timeout, userDataDir, args, executablePath, logLevel, indent }: {
|
||||
defaultViewport: Viewport;
|
||||
timeout: number;
|
||||
userDataDir: string;
|
||||
args: string[];
|
||||
executablePath: string;
|
||||
logLevel: LogLevel;
|
||||
indent: boolean;
|
||||
}): Promise<HeadlessBrowser>;
|
||||
connection: Connection;
|
||||
id: string;
|
||||
runner: BrowserRunner;
|
||||
get _targets(): Map<string, Target>;
|
||||
constructor({ connection, defaultViewport, runner }: {
|
||||
connection: Connection;
|
||||
defaultViewport: Viewport;
|
||||
runner: BrowserRunner;
|
||||
});
|
||||
browserContexts(): BrowserContext[];
|
||||
newPage({ context, logLevel, indent, pageIndex, onBrowserLog, onLog }: {
|
||||
context: SourceMapGetter;
|
||||
logLevel: LogLevel;
|
||||
indent: boolean;
|
||||
pageIndex: number;
|
||||
onBrowserLog: null | ((log: BrowserLog) => void);
|
||||
onLog: OnLog;
|
||||
}): Promise<Page>;
|
||||
_createPageInContext({ context, logLevel, indent, pageIndex, onBrowserLog, onLog }: {
|
||||
context: SourceMapGetter;
|
||||
logLevel: LogLevel;
|
||||
indent: boolean;
|
||||
pageIndex: number;
|
||||
onBrowserLog: null | ((log: BrowserLog) => void);
|
||||
onLog: OnLog;
|
||||
}): Promise<Page>;
|
||||
targets(): Target[];
|
||||
waitForTarget(predicate: (x: Target) => boolean | Promise<boolean>, options?: WaitForTargetOptions): Promise<Target>;
|
||||
pages(): Promise<Page[]>;
|
||||
close({ silent }: {
|
||||
silent: boolean;
|
||||
}): Promise<void>;
|
||||
disconnect(): void;
|
||||
}
|
||||
export declare class BrowserContext extends EventEmitter {
|
||||
#private;
|
||||
constructor(browser: HeadlessBrowser);
|
||||
targets(): Target[];
|
||||
waitForTarget(predicate: (x: Target) => boolean | Promise<boolean>, options?: {
|
||||
timeout?: number;
|
||||
}): Promise<Target>;
|
||||
pages(): Promise<Page[]>;
|
||||
newPage({ context, logLevel, indent, pageIndex, onBrowserLog, onLog }: {
|
||||
context: SourceMapGetter;
|
||||
logLevel: LogLevel;
|
||||
indent: boolean;
|
||||
pageIndex: number;
|
||||
onBrowserLog: null | ((log: BrowserLog) => void);
|
||||
onLog: OnLog;
|
||||
}): Promise<Page>;
|
||||
browser(): HeadlessBrowser;
|
||||
}
|
||||
export {};
|
||||
Generated
Vendored
+237
@@ -0,0 +1,237 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.BrowserContext = exports.HeadlessBrowser = void 0;
|
||||
const assert_1 = require("./assert");
|
||||
const BrowserRunner_1 = require("./BrowserRunner");
|
||||
const EventEmitter_1 = require("./EventEmitter");
|
||||
const Target_1 = require("./Target");
|
||||
const util_1 = require("./util");
|
||||
class HeadlessBrowser extends EventEmitter_1.EventEmitter {
|
||||
static async create({ defaultViewport, timeout, userDataDir, args, executablePath, logLevel, indent, }) {
|
||||
const runner = await (0, BrowserRunner_1.makeBrowserRunner)({
|
||||
executablePath,
|
||||
processArguments: args,
|
||||
userDataDir,
|
||||
indent,
|
||||
logLevel,
|
||||
timeout,
|
||||
});
|
||||
const browser = new HeadlessBrowser({
|
||||
connection: runner.connection,
|
||||
defaultViewport,
|
||||
runner,
|
||||
});
|
||||
await runner.connection.send('Target.setDiscoverTargets', { discover: true });
|
||||
return browser;
|
||||
}
|
||||
#defaultViewport;
|
||||
connection;
|
||||
#defaultContext;
|
||||
#contexts;
|
||||
#targets;
|
||||
id;
|
||||
runner;
|
||||
get _targets() {
|
||||
return this.#targets;
|
||||
}
|
||||
constructor({ connection, defaultViewport, runner, }) {
|
||||
super();
|
||||
this.#defaultViewport = defaultViewport;
|
||||
this.connection = connection;
|
||||
this.id = Math.random().toString(36).substring(2, 15);
|
||||
this.#defaultContext = new BrowserContext(this);
|
||||
this.#contexts = new Map();
|
||||
this.#targets = new Map();
|
||||
this.connection.on('Target.targetCreated', this.#targetCreated.bind(this));
|
||||
this.connection.on('Target.targetDestroyed', this.#targetDestroyed.bind(this));
|
||||
this.connection.on('Target.targetInfoChanged', this.#targetInfoChanged.bind(this));
|
||||
this.runner = runner;
|
||||
}
|
||||
browserContexts() {
|
||||
return [this.#defaultContext, ...Array.from(this.#contexts.values())];
|
||||
}
|
||||
async #targetCreated(event) {
|
||||
var _a;
|
||||
const { targetInfo } = event;
|
||||
const { browserContextId } = targetInfo;
|
||||
const context = browserContextId && this.#contexts.has(browserContextId)
|
||||
? this.#contexts.get(browserContextId)
|
||||
: this.#defaultContext;
|
||||
if (!context) {
|
||||
throw new Error('Missing browser context');
|
||||
}
|
||||
const target = new Target_1.Target(targetInfo, context, () => {
|
||||
return this.connection.createSession(targetInfo);
|
||||
}, (_a = this.#defaultViewport) !== null && _a !== void 0 ? _a : null);
|
||||
(0, assert_1.assert)(!this.#targets.has(event.targetInfo.targetId), 'Target should not exist before targetCreated');
|
||||
this.#targets.set(event.targetInfo.targetId, target);
|
||||
if (await target._initializedPromise) {
|
||||
this.emit("targetcreated" /* BrowserEmittedEvents.TargetCreated */, target);
|
||||
}
|
||||
}
|
||||
#targetDestroyed(event) {
|
||||
const target = this.#targets.get(event.targetId);
|
||||
if (!target) {
|
||||
throw new Error(`Missing target in _targetDestroyed (id = ${event.targetId})`);
|
||||
}
|
||||
target._initializedCallback(false);
|
||||
this.#targets.delete(event.targetId);
|
||||
target._closedCallback();
|
||||
}
|
||||
#targetInfoChanged(event) {
|
||||
const target = this.#targets.get(event.targetInfo.targetId);
|
||||
if (!target) {
|
||||
throw new Error(`Missing target in targetInfoChanged (id = ${event.targetInfo.targetId})`);
|
||||
}
|
||||
const previousURL = target.url();
|
||||
const wasInitialized = target._isInitialized;
|
||||
target._targetInfoChanged(event.targetInfo);
|
||||
if (wasInitialized && previousURL !== target.url()) {
|
||||
this.emit("targetchanged" /* BrowserEmittedEvents.TargetChanged */, target);
|
||||
}
|
||||
}
|
||||
newPage({ context, logLevel, indent, pageIndex, onBrowserLog, onLog, }) {
|
||||
return this.#defaultContext.newPage({
|
||||
context,
|
||||
logLevel,
|
||||
indent,
|
||||
pageIndex,
|
||||
onBrowserLog,
|
||||
onLog,
|
||||
});
|
||||
}
|
||||
async _createPageInContext({ context, logLevel, indent, pageIndex, onBrowserLog, onLog, }) {
|
||||
const { value: { targetId }, } = await this.connection.send('Target.createTarget', {
|
||||
url: 'about:blank',
|
||||
browserContextId: undefined,
|
||||
});
|
||||
const target = this.#targets.get(targetId);
|
||||
if (!target) {
|
||||
throw new Error(`Missing target for page (id = ${targetId})`);
|
||||
}
|
||||
const initialized = await target._initializedPromise;
|
||||
if (!initialized) {
|
||||
throw new Error(`Failed to create target for page (id = ${targetId})`);
|
||||
}
|
||||
const page = await target.page({
|
||||
sourceMapGetter: context,
|
||||
logLevel,
|
||||
indent,
|
||||
pageIndex,
|
||||
onBrowserLog,
|
||||
onLog,
|
||||
});
|
||||
if (!page) {
|
||||
throw new Error(`Failed to create a page for context`);
|
||||
}
|
||||
return page;
|
||||
}
|
||||
targets() {
|
||||
return Array.from(this.#targets.values()).filter((target) => {
|
||||
return target._isInitialized;
|
||||
});
|
||||
}
|
||||
async waitForTarget(predicate, options = {}) {
|
||||
const { timeout = 30000 } = options;
|
||||
let resolve;
|
||||
let isResolved = false;
|
||||
const targetPromise = new Promise((x) => {
|
||||
resolve = x;
|
||||
});
|
||||
this.on("targetcreated" /* BrowserEmittedEvents.TargetCreated */, check);
|
||||
this.on("targetchanged" /* BrowserEmittedEvents.TargetChanged */, check);
|
||||
try {
|
||||
if (!timeout) {
|
||||
return await targetPromise;
|
||||
}
|
||||
this.targets().forEach(check);
|
||||
return await (0, util_1.waitWithTimeout)(targetPromise, 'target', timeout, this);
|
||||
}
|
||||
finally {
|
||||
this.off("targetcreated" /* BrowserEmittedEvents.TargetCreated */, check);
|
||||
this.off("targetchanged" /* BrowserEmittedEvents.TargetChanged */, check);
|
||||
}
|
||||
async function check(target) {
|
||||
if ((await predicate(target)) && !isResolved) {
|
||||
isResolved = true;
|
||||
resolve(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
async pages() {
|
||||
const contextPages = await Promise.all(this.browserContexts().map((context) => {
|
||||
return context.pages();
|
||||
}));
|
||||
// Flatten array.
|
||||
return contextPages.reduce((acc, x) => {
|
||||
return acc.concat(x);
|
||||
}, []);
|
||||
}
|
||||
async close({ silent }) {
|
||||
await this.runner.closeProcess();
|
||||
(await this.pages()).forEach((page) => {
|
||||
page.emit("disposed" /* PageEmittedEvents.Disposed */);
|
||||
page.closed = true;
|
||||
});
|
||||
this.disconnect();
|
||||
this.emit(silent ? "closed-silent" /* BrowserEmittedEvents.ClosedSilent */ : "closed" /* BrowserEmittedEvents.Closed */);
|
||||
}
|
||||
disconnect() {
|
||||
this.connection.dispose();
|
||||
}
|
||||
}
|
||||
exports.HeadlessBrowser = HeadlessBrowser;
|
||||
class BrowserContext extends EventEmitter_1.EventEmitter {
|
||||
#browser;
|
||||
constructor(browser) {
|
||||
super();
|
||||
this.#browser = browser;
|
||||
}
|
||||
targets() {
|
||||
return this.#browser.targets().filter((target) => {
|
||||
return target.browserContext() === this;
|
||||
});
|
||||
}
|
||||
waitForTarget(predicate, options = {}) {
|
||||
return this.#browser.waitForTarget((target) => {
|
||||
return target.browserContext() === this && predicate(target);
|
||||
}, options);
|
||||
}
|
||||
async pages() {
|
||||
const pages = await Promise.all(this.targets()
|
||||
.filter((target) => target.type() === 'page')
|
||||
.map((target) => target.expectPage()));
|
||||
return pages.filter((page) => {
|
||||
return Boolean(page);
|
||||
});
|
||||
}
|
||||
newPage({ context, logLevel, indent, pageIndex, onBrowserLog, onLog, }) {
|
||||
return this.#browser._createPageInContext({
|
||||
context,
|
||||
logLevel,
|
||||
indent,
|
||||
pageIndex,
|
||||
onBrowserLog,
|
||||
onLog,
|
||||
});
|
||||
}
|
||||
browser() {
|
||||
return this.#browser;
|
||||
}
|
||||
}
|
||||
exports.BrowserContext = BrowserContext;
|
||||
Generated
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
import type { DownloadBrowserProgressFn } from '../options/on-browser-download';
|
||||
import { TESTED_VERSION } from './get-chrome-download-url';
|
||||
export { TESTED_VERSION };
|
||||
interface BrowserFetcherRevisionInfo {
|
||||
folderPath: string;
|
||||
executablePath: string;
|
||||
url: string;
|
||||
local: boolean;
|
||||
}
|
||||
export declare const readVersionFile: (chromeMode: "chrome-for-testing" | "headless-shell") => string | null;
|
||||
export declare const downloadBrowser: ({ logLevel, indent, onProgress, version, chromeMode, }: {
|
||||
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
||||
indent: boolean;
|
||||
onProgress: DownloadBrowserProgressFn;
|
||||
version: string | null;
|
||||
chromeMode: "chrome-for-testing" | "headless-shell";
|
||||
}) => Promise<BrowserFetcherRevisionInfo | undefined>;
|
||||
export declare const getRevisionInfo: (chromeMode: "chrome-for-testing" | "headless-shell") => BrowserFetcherRevisionInfo;
|
||||
Generated
Vendored
+246
@@ -0,0 +1,246 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2017 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 () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getRevisionInfo = exports.downloadBrowser = exports.readVersionFile = exports.TESTED_VERSION = void 0;
|
||||
const fs = __importStar(require("node:fs"));
|
||||
const os = __importStar(require("node:os"));
|
||||
const path = __importStar(require("node:path"));
|
||||
const extract_zip_1 = __importDefault(require("extract-zip"));
|
||||
const node_util_1 = require("node:util");
|
||||
const download_file_1 = require("../assets/download-file");
|
||||
const make_file_executable_1 = require("../compositor/make-file-executable");
|
||||
const get_chrome_download_url_1 = require("./get-chrome-download-url");
|
||||
Object.defineProperty(exports, "TESTED_VERSION", { enumerable: true, get: function () { return get_chrome_download_url_1.TESTED_VERSION; } });
|
||||
const get_download_destination_1 = require("./get-download-destination");
|
||||
const mkdirAsync = fs.promises.mkdir;
|
||||
const unlinkAsync = (0, node_util_1.promisify)(fs.unlink.bind(fs));
|
||||
function existsAsync(filePath) {
|
||||
return new Promise((resolve) => {
|
||||
fs.access(filePath, (err) => {
|
||||
return resolve(!err);
|
||||
});
|
||||
});
|
||||
}
|
||||
const getPlatform = () => {
|
||||
const platform = os.platform();
|
||||
switch (platform) {
|
||||
case 'darwin':
|
||||
return os.arch() === 'arm64' ? 'mac-arm64' : 'mac-x64';
|
||||
case 'linux':
|
||||
return os.arch() === 'arm64' ? 'linux-arm64' : 'linux64';
|
||||
case 'win32':
|
||||
return 'win64';
|
||||
default:
|
||||
throw new Error('Unsupported platform: ' + platform);
|
||||
}
|
||||
};
|
||||
const getDownloadsFolder = (chromeMode) => {
|
||||
const destination = chromeMode === 'headless-shell'
|
||||
? 'chrome-headless-shell'
|
||||
: 'chrome-for-testing';
|
||||
return path.join((0, get_download_destination_1.getDownloadsCacheDir)(), destination);
|
||||
};
|
||||
const getVersionFilePath = (chromeMode) => {
|
||||
const downloadsFolder = getDownloadsFolder(chromeMode);
|
||||
return path.join(downloadsFolder, 'VERSION');
|
||||
};
|
||||
const getExpectedVersion = (version, _chromeMode) => {
|
||||
if (version) {
|
||||
return version;
|
||||
}
|
||||
return get_chrome_download_url_1.TESTED_VERSION;
|
||||
};
|
||||
const readVersionFile = (chromeMode) => {
|
||||
const versionFilePath = getVersionFilePath(chromeMode);
|
||||
try {
|
||||
return fs.readFileSync(versionFilePath, 'utf-8').trim();
|
||||
}
|
||||
catch (_a) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
exports.readVersionFile = readVersionFile;
|
||||
const writeVersionFile = (chromeMode, version) => {
|
||||
const versionFilePath = getVersionFilePath(chromeMode);
|
||||
fs.writeFileSync(versionFilePath, version);
|
||||
};
|
||||
const downloadBrowser = async ({ logLevel, indent, onProgress, version, chromeMode, }) => {
|
||||
const platform = getPlatform();
|
||||
const downloadURL = (0, get_chrome_download_url_1.getChromeDownloadUrl)({ platform, version, chromeMode });
|
||||
const fileName = downloadURL.split('/').pop();
|
||||
if (!fileName) {
|
||||
throw new Error(`A malformed download URL was found: ${downloadURL}.`);
|
||||
}
|
||||
const downloadsFolder = getDownloadsFolder(chromeMode);
|
||||
const archivePath = path.join(downloadsFolder, fileName);
|
||||
const outputPath = getFolderPath(downloadsFolder, platform);
|
||||
const expectedVersion = getExpectedVersion(version, chromeMode);
|
||||
if (await existsAsync(outputPath)) {
|
||||
const installedVersion = (0, exports.readVersionFile)(chromeMode);
|
||||
if (installedVersion === expectedVersion) {
|
||||
return (0, exports.getRevisionInfo)(chromeMode);
|
||||
}
|
||||
// VERSION file missing or mismatched - delete and re-download
|
||||
fs.rmSync(outputPath, { recursive: true, force: true });
|
||||
}
|
||||
if (!(await existsAsync(downloadsFolder))) {
|
||||
await mkdirAsync(downloadsFolder, {
|
||||
recursive: true,
|
||||
});
|
||||
}
|
||||
if (os.platform() !== 'darwin' &&
|
||||
os.platform() !== 'linux' &&
|
||||
os.arch() === 'arm64') {
|
||||
throw new Error([
|
||||
'Chrome Headless Shell is not available for Windows for arm64 architecture.',
|
||||
].join('\n'));
|
||||
}
|
||||
(0, get_chrome_download_url_1.logDownloadUrl)({ url: downloadURL, logLevel, indent });
|
||||
try {
|
||||
await (0, download_file_1.downloadFile)({
|
||||
url: downloadURL,
|
||||
to: () => archivePath,
|
||||
onProgress: (progress) => {
|
||||
if (progress.totalSize === null || progress.percent === null) {
|
||||
throw new Error('Expected totalSize and percent to be defined');
|
||||
}
|
||||
onProgress({
|
||||
downloadedBytes: progress.downloaded,
|
||||
totalSizeInBytes: progress.totalSize,
|
||||
percent: progress.percent,
|
||||
alreadyAvailable: false,
|
||||
});
|
||||
},
|
||||
indent,
|
||||
logLevel,
|
||||
abortSignal: new AbortController().signal,
|
||||
});
|
||||
await (0, extract_zip_1.default)(archivePath, { dir: outputPath });
|
||||
const possibleSubdirs = [
|
||||
'chrome-linux',
|
||||
'chrome-headless-shell-linux64',
|
||||
'chromium-headless-shell-amazon-linux2023-arm64',
|
||||
'chromium-headless-shell-amazon-linux2023-x64',
|
||||
];
|
||||
for (const subdir of possibleSubdirs) {
|
||||
const chromeLinuxFolder = path.join(outputPath, subdir);
|
||||
const chromePath = path.join(chromeLinuxFolder, 'chrome');
|
||||
if (fs.existsSync(chromePath)) {
|
||||
const chromeHeadlessShellPath = path.join(chromeLinuxFolder, 'chrome-headless-shell');
|
||||
fs.renameSync(chromePath, chromeHeadlessShellPath);
|
||||
}
|
||||
if (fs.existsSync(chromeLinuxFolder)) {
|
||||
const targetFolder = path.join(outputPath, 'chrome-headless-shell-' + platform);
|
||||
if (chromeLinuxFolder !== targetFolder) {
|
||||
fs.renameSync(chromeLinuxFolder, targetFolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
finally {
|
||||
if (await existsAsync(archivePath)) {
|
||||
await unlinkAsync(archivePath);
|
||||
}
|
||||
}
|
||||
writeVersionFile(chromeMode, expectedVersion);
|
||||
const revisionInfo = (0, exports.getRevisionInfo)(chromeMode);
|
||||
(0, make_file_executable_1.makeFileExecutableIfItIsNot)(revisionInfo.executablePath);
|
||||
return revisionInfo;
|
||||
};
|
||||
exports.downloadBrowser = downloadBrowser;
|
||||
const getFolderPath = (downloadsFolder, platform) => {
|
||||
return path.resolve(downloadsFolder, platform);
|
||||
};
|
||||
const getExecutablePath = (chromeMode) => {
|
||||
const downloadsFolder = getDownloadsFolder(chromeMode);
|
||||
const platform = getPlatform();
|
||||
const folderPath = getFolderPath(downloadsFolder, platform);
|
||||
if (chromeMode === 'chrome-for-testing') {
|
||||
if (platform === 'mac-arm64' || platform === 'mac-x64') {
|
||||
return path.join(folderPath, `chrome-${platform}`, 'Google Chrome for Testing.app/Contents/MacOS/Google Chrome for Testing');
|
||||
}
|
||||
if (platform === 'win64') {
|
||||
return path.join(folderPath, 'chrome-win64', 'chrome.exe');
|
||||
}
|
||||
if (platform === 'linux64' || platform === 'linux-arm64') {
|
||||
return path.join(folderPath, 'chrome-linux64', 'chrome');
|
||||
}
|
||||
throw new Error('unsupported platform' + platform);
|
||||
}
|
||||
if (chromeMode === 'headless-shell') {
|
||||
return path.join(folderPath, `chrome-headless-shell-${platform}`, platform === 'win64'
|
||||
? 'chrome-headless-shell.exe'
|
||||
: platform === 'linux-arm64' || (0, get_chrome_download_url_1.isAmazonLinux2023)()
|
||||
? 'headless_shell'
|
||||
: 'chrome-headless-shell');
|
||||
}
|
||||
throw new Error('unsupported chrome mode' + chromeMode);
|
||||
};
|
||||
const getRevisionInfo = (chromeMode) => {
|
||||
const executablePath = getExecutablePath(chromeMode);
|
||||
const downloadsFolder = getDownloadsFolder(chromeMode);
|
||||
const platform = getPlatform();
|
||||
const folderPath = getFolderPath(downloadsFolder, platform);
|
||||
const url = (0, get_chrome_download_url_1.getChromeDownloadUrl)({ platform, version: null, chromeMode });
|
||||
const local = fs.existsSync(folderPath);
|
||||
return {
|
||||
executablePath,
|
||||
folderPath,
|
||||
local,
|
||||
url,
|
||||
};
|
||||
};
|
||||
exports.getRevisionInfo = getRevisionInfo;
|
||||
Generated
Vendored
+105
@@ -0,0 +1,105 @@
|
||||
import { BrowserLog } from '../browser-log';
|
||||
import type { LogLevel } from '../log-level';
|
||||
import type { HeadlessBrowser } from './Browser';
|
||||
import type { CDPSession } from './Connection';
|
||||
import { ConsoleMessage } from './ConsoleMessage';
|
||||
import type { EvaluateFn, EvaluateFnReturnType, EvaluateHandleFn, SerializableOrJSHandle, UnwrapPromiseLike } from './EvalTypes';
|
||||
import { EventEmitter } from './EventEmitter';
|
||||
import type { Frame } from './FrameManager';
|
||||
import type { HTTPResponse } from './HTTPResponse';
|
||||
import type { JSHandle } from './JSHandle';
|
||||
import type { Viewport } from './PuppeteerViewport';
|
||||
import type { Target } from './Target';
|
||||
import { TaskQueue } from './TaskQueue';
|
||||
import type { SourceMapGetter } from './source-map-getter';
|
||||
interface WaitForOptions {
|
||||
timeout?: number;
|
||||
}
|
||||
export declare const enum PageEmittedEvents {
|
||||
Error = "error",
|
||||
Disposed = "disposed"
|
||||
}
|
||||
interface PageEventObject {
|
||||
console: ConsoleMessage;
|
||||
error: Error;
|
||||
disposed: undefined;
|
||||
}
|
||||
export type OnLog = ({ logLevel, previewString, tag }: {
|
||||
logLevel: LogLevel;
|
||||
tag: string;
|
||||
previewString: string;
|
||||
}) => void;
|
||||
export declare class Page extends EventEmitter {
|
||||
#private;
|
||||
id: string;
|
||||
static _create({ client, target, defaultViewport, browser, sourceMapGetter, logLevel, indent, pageIndex, onBrowserLog, onLog }: {
|
||||
client: CDPSession;
|
||||
target: Target;
|
||||
defaultViewport: Viewport;
|
||||
browser: HeadlessBrowser;
|
||||
sourceMapGetter: SourceMapGetter;
|
||||
logLevel: LogLevel;
|
||||
indent: boolean;
|
||||
pageIndex: number;
|
||||
onBrowserLog: null | ((log: BrowserLog) => void);
|
||||
onLog: OnLog;
|
||||
}): Promise<Page>;
|
||||
closed: boolean;
|
||||
browser: HeadlessBrowser;
|
||||
screenshotTaskQueue: TaskQueue;
|
||||
sourceMapGetter: SourceMapGetter;
|
||||
logLevel: LogLevel;
|
||||
indent: boolean;
|
||||
pageIndex: number;
|
||||
onBrowserLog: null | ((log: BrowserLog) => void);
|
||||
onLog: OnLog;
|
||||
constructor({ client, target, browser, sourceMapGetter, logLevel, indent, pageIndex, onBrowserLog, onLog }: {
|
||||
client: CDPSession;
|
||||
target: Target;
|
||||
browser: HeadlessBrowser;
|
||||
sourceMapGetter: SourceMapGetter;
|
||||
logLevel: LogLevel;
|
||||
indent: boolean;
|
||||
pageIndex: number;
|
||||
onBrowserLog: null | ((log: BrowserLog) => void);
|
||||
onLog: OnLog;
|
||||
});
|
||||
/**
|
||||
* Listen to page events.
|
||||
*/
|
||||
on<K extends keyof PageEventObject>(eventName: K, handler: (event: PageEventObject[K]) => void): EventEmitter;
|
||||
once<K extends keyof PageEventObject>(eventName: K, handler: (event: PageEventObject[K]) => void): EventEmitter;
|
||||
off<K extends keyof PageEventObject>(eventName: K, handler: (event: PageEventObject[K]) => void): EventEmitter;
|
||||
/**
|
||||
* @returns A target this page was created from.
|
||||
*/
|
||||
target(): Target;
|
||||
_client(): CDPSession;
|
||||
/**
|
||||
* @returns The page's main frame.
|
||||
* @remarks
|
||||
* Page is guaranteed to have a main frame which persists during navigations.
|
||||
*/
|
||||
mainFrame(): Frame;
|
||||
setViewport(viewport: Viewport): Promise<void>;
|
||||
setDefaultNavigationTimeout(timeout: number): void;
|
||||
setDefaultTimeout(timeout: number): void;
|
||||
evaluateHandle<HandlerType extends JSHandle = JSHandle>(pageFunction: EvaluateHandleFn, ...args: SerializableOrJSHandle[]): Promise<HandlerType>;
|
||||
url(): string;
|
||||
goto({ url, timeout, options }: {
|
||||
url: string;
|
||||
timeout: number;
|
||||
options?: WaitForOptions & {
|
||||
referer?: string;
|
||||
};
|
||||
}): Promise<HTTPResponse | null>;
|
||||
bringToFront(): Promise<void>;
|
||||
setAutoDarkModeOverride(): Promise<void>;
|
||||
evaluate<T extends EvaluateFn>(pageFunction: T, ...args: SerializableOrJSHandle[]): Promise<UnwrapPromiseLike<EvaluateFnReturnType<T>>>;
|
||||
evaluateOnNewDocument(pageFunction: Function | string, ...args: unknown[]): Promise<void>;
|
||||
close(options?: {
|
||||
runBeforeUnload?: boolean;
|
||||
}): Promise<void>;
|
||||
setBrowserSourceMapGetter(context: SourceMapGetter): void;
|
||||
}
|
||||
export {};
|
||||
Generated
Vendored
+454
@@ -0,0 +1,454 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Page = void 0;
|
||||
/**
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
const no_react_1 = require("remotion/no-react");
|
||||
const format_logs_1 = require("../format-logs");
|
||||
const logger_1 = require("../logger");
|
||||
const truthy_1 = require("../truthy");
|
||||
const ConsoleMessage_1 = require("./ConsoleMessage");
|
||||
const EventEmitter_1 = require("./EventEmitter");
|
||||
const FrameManager_1 = require("./FrameManager");
|
||||
const JSHandle_1 = require("./JSHandle");
|
||||
const TaskQueue_1 = require("./TaskQueue");
|
||||
const TimeoutSettings_1 = require("./TimeoutSettings");
|
||||
const assert_1 = require("./assert");
|
||||
const util_1 = require("./util");
|
||||
const shouldHideWarning = (log) => {
|
||||
// Mixed Content warnings caused by localhost should not be displayed
|
||||
if (log.text.includes('Mixed Content:') &&
|
||||
log.text.includes('http://localhost:')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const format = (eventType, args) => {
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h;
|
||||
const previewString = args
|
||||
.filter((a) => {
|
||||
var _a;
|
||||
return !(a.type === 'symbol' && ((_a = a.description) === null || _a === void 0 ? void 0 : _a.includes(`__remotion_`)));
|
||||
})
|
||||
.map((a) => (0, format_logs_1.formatRemoteObject)(a))
|
||||
.filter(Boolean)
|
||||
.join(' ');
|
||||
let logLevelFromRemotionLog = null;
|
||||
let tag = null;
|
||||
for (const a of args) {
|
||||
if (a.type === 'symbol' && ((_a = a.description) === null || _a === void 0 ? void 0 : _a.includes(`__remotion_level_`))) {
|
||||
logLevelFromRemotionLog = (_d = (_c = (_b = a.description) === null || _b === void 0 ? void 0 : _b.split('__remotion_level_')) === null || _c === void 0 ? void 0 : _c[1]) === null || _d === void 0 ? void 0 : _d.replace(')', '');
|
||||
}
|
||||
if (a.type === 'symbol' && ((_e = a.description) === null || _e === void 0 ? void 0 : _e.includes(`__remotion_tag_`))) {
|
||||
tag = (_h = (_g = (_f = a.description) === null || _f === void 0 ? void 0 : _f.split('__remotion_tag_')) === null || _g === void 0 ? void 0 : _g[1]) === null || _h === void 0 ? void 0 : _h.replace(')', '');
|
||||
}
|
||||
}
|
||||
const logLevelFromEvent = eventType === 'debug'
|
||||
? 'verbose'
|
||||
: eventType === 'error'
|
||||
? 'error'
|
||||
: eventType === 'warning'
|
||||
? 'warn'
|
||||
: 'verbose';
|
||||
return { previewString, logLevelFromRemotionLog, logLevelFromEvent, tag };
|
||||
};
|
||||
class Page extends EventEmitter_1.EventEmitter {
|
||||
id;
|
||||
static async _create({ client, target, defaultViewport, browser, sourceMapGetter, logLevel, indent, pageIndex, onBrowserLog, onLog, }) {
|
||||
const page = new Page({
|
||||
client,
|
||||
target,
|
||||
browser,
|
||||
sourceMapGetter,
|
||||
logLevel,
|
||||
indent,
|
||||
pageIndex,
|
||||
onBrowserLog,
|
||||
onLog,
|
||||
});
|
||||
await page.#initialize();
|
||||
await page.setViewport(defaultViewport);
|
||||
return page;
|
||||
}
|
||||
closed = false;
|
||||
#client;
|
||||
#target;
|
||||
#timeoutSettings = new TimeoutSettings_1.TimeoutSettings();
|
||||
#frameManager;
|
||||
#pageBindings = new Map();
|
||||
browser;
|
||||
screenshotTaskQueue;
|
||||
sourceMapGetter;
|
||||
logLevel;
|
||||
indent;
|
||||
pageIndex;
|
||||
onBrowserLog;
|
||||
onLog;
|
||||
constructor({ client, target, browser, sourceMapGetter, logLevel, indent, pageIndex, onBrowserLog, onLog, }) {
|
||||
super();
|
||||
this.#client = client;
|
||||
this.#target = target;
|
||||
this.#frameManager = new FrameManager_1.FrameManager(client, this, indent, logLevel);
|
||||
this.screenshotTaskQueue = new TaskQueue_1.TaskQueue();
|
||||
this.browser = browser;
|
||||
this.id = String(Math.random());
|
||||
this.sourceMapGetter = sourceMapGetter;
|
||||
this.logLevel = logLevel;
|
||||
this.indent = indent;
|
||||
this.pageIndex = pageIndex;
|
||||
this.onBrowserLog = onBrowserLog;
|
||||
this.onLog = onLog;
|
||||
client.on('Target.attachedToTarget', (event) => {
|
||||
switch (event.targetInfo.type) {
|
||||
case 'iframe':
|
||||
break;
|
||||
case 'worker':
|
||||
break;
|
||||
default:
|
||||
// If we don't detach from service workers, they will never die.
|
||||
// We still want to attach to workers for emitting events.
|
||||
// We still want to attach to iframes so sessions may interact with them.
|
||||
// We detach from all other types out of an abundance of caution.
|
||||
// See https://source.chromium.org/chromium/chromium/src/+/main:content/browser/devtools/devtools_agent_host_impl.cc?ss=chromium&q=f:devtools%20-f:out%20%22::kTypePage%5B%5D%22
|
||||
// for the complete list of available types.
|
||||
client
|
||||
.send('Target.detachFromTarget', {
|
||||
sessionId: event.sessionId,
|
||||
})
|
||||
.catch((err) => logger_1.Log.error({ indent, logLevel }, err));
|
||||
}
|
||||
});
|
||||
client.on('Runtime.consoleAPICalled', (event) => {
|
||||
return this.#onConsoleAPI(event);
|
||||
});
|
||||
client.on('Runtime.bindingCalled', (event) => {
|
||||
return this.#onBindingCalled(event);
|
||||
});
|
||||
client.on('Inspector.targetCrashed', () => {
|
||||
return this.#onTargetCrashed();
|
||||
});
|
||||
client.on('Log.entryAdded', (event) => {
|
||||
return this.#onLogEntryAdded(event);
|
||||
});
|
||||
}
|
||||
#onConsole = (log) => {
|
||||
var _a, _b;
|
||||
var _c;
|
||||
const stackTrace = log.stackTrace();
|
||||
const { url, columnNumber, lineNumber } = (_c = stackTrace[0]) !== null && _c !== void 0 ? _c : {};
|
||||
const logLevel = this.logLevel;
|
||||
const indent = this.indent;
|
||||
if (shouldHideWarning(log)) {
|
||||
return;
|
||||
}
|
||||
(_a = this.onBrowserLog) === null || _a === void 0 ? void 0 : _a.call(this, {
|
||||
stackTrace,
|
||||
text: log.text,
|
||||
type: log.type,
|
||||
});
|
||||
if ((url === null || url === void 0 ? void 0 : url.endsWith(no_react_1.NoReactInternals.bundleName)) &&
|
||||
lineNumber &&
|
||||
this.sourceMapGetter()) {
|
||||
const origPosition = (_b = this.sourceMapGetter()) === null || _b === void 0 ? void 0 : _b.originalPositionFor({
|
||||
column: columnNumber !== null && columnNumber !== void 0 ? columnNumber : 0,
|
||||
line: lineNumber,
|
||||
});
|
||||
const file = [
|
||||
origPosition === null || origPosition === void 0 ? void 0 : origPosition.source,
|
||||
origPosition === null || origPosition === void 0 ? void 0 : origPosition.line,
|
||||
origPosition === null || origPosition === void 0 ? void 0 : origPosition.column,
|
||||
]
|
||||
.filter(truthy_1.truthy)
|
||||
.join(':');
|
||||
const isDelayRenderClear = log.previewString.includes(no_react_1.NoReactInternals.DELAY_RENDER_CLEAR_TOKEN);
|
||||
const tabInfo = `Tab ${this.pageIndex}`;
|
||||
const tagInfo = [origPosition === null || origPosition === void 0 ? void 0 : origPosition.name, isDelayRenderClear ? null : file]
|
||||
.filter(truthy_1.truthy)
|
||||
.join('@');
|
||||
const tag = [tabInfo, log.tag, log.tag ? null : tagInfo]
|
||||
.filter(truthy_1.truthy)
|
||||
.join(', ');
|
||||
this.onLog({
|
||||
logLevel: log.logLevel,
|
||||
tag,
|
||||
previewString: log.previewString,
|
||||
});
|
||||
}
|
||||
else if (log.type === 'error') {
|
||||
if (log.text.includes('Failed to load resource:')) {
|
||||
logger_1.Log.error({ logLevel, tag: url, indent },
|
||||
// Sometimes the log is like this:
|
||||
// Failed to load resource: the server responded with a status of 404 ()
|
||||
// We remove the empty parentheses.
|
||||
log.text.replace(/\(\)$/, ''));
|
||||
}
|
||||
else {
|
||||
logger_1.Log.error({ logLevel, tag: `console.${log.type}`, indent }, log.text);
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger_1.Log.verbose({ logLevel, tag: `console.${log.type}`, indent }, log.text);
|
||||
}
|
||||
};
|
||||
async #initialize() {
|
||||
await Promise.all([
|
||||
this.#frameManager.initialize(),
|
||||
this.#client.send('Target.setAutoAttach', {
|
||||
autoAttach: true,
|
||||
waitForDebuggerOnStart: false,
|
||||
flatten: true,
|
||||
}),
|
||||
this.#client.send('Performance.enable'),
|
||||
this.#client.send('Log.enable'),
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* Listen to page events.
|
||||
*/
|
||||
// Note: this method exists to define event typings and handle
|
||||
// proper wireup of cooperative request interception. Actual event listening and
|
||||
// dispatching is delegated to EventEmitter.
|
||||
on(eventName, handler) {
|
||||
return super.on(eventName, handler);
|
||||
}
|
||||
once(eventName, handler) {
|
||||
// Note: this method only exists to define the types; we delegate the impl
|
||||
// to EventEmitter.
|
||||
return super.once(eventName, handler);
|
||||
}
|
||||
off(eventName, handler) {
|
||||
return super.off(eventName, handler);
|
||||
}
|
||||
/**
|
||||
* @returns A target this page was created from.
|
||||
*/
|
||||
target() {
|
||||
return this.#target;
|
||||
}
|
||||
_client() {
|
||||
return this.#client;
|
||||
}
|
||||
#onTargetCrashed() {
|
||||
// This error message is being checked against in is-flaky-error.ts
|
||||
this.emit('error', new Error('Page crashed!'));
|
||||
}
|
||||
#onLogEntryAdded(event) {
|
||||
var _a;
|
||||
const { level, text, args, source, url, lineNumber } = event.entry;
|
||||
if (args) {
|
||||
args.map((arg) => {
|
||||
return (0, util_1.releaseObject)(this.#client, arg);
|
||||
});
|
||||
}
|
||||
const { previewString, logLevelFromRemotionLog, logLevelFromEvent, tag } = format(level, args !== null && args !== void 0 ? args : []);
|
||||
if (source !== 'worker') {
|
||||
const message = new ConsoleMessage_1.ConsoleMessage({
|
||||
type: level,
|
||||
text,
|
||||
args: [],
|
||||
stackTraceLocations: [{ url, lineNumber }],
|
||||
previewString,
|
||||
logLevel: logLevelFromRemotionLog !== null && logLevelFromRemotionLog !== void 0 ? logLevelFromRemotionLog : logLevelFromEvent,
|
||||
tag,
|
||||
});
|
||||
(_a = this.onBrowserLog) === null || _a === void 0 ? void 0 : _a.call(this, {
|
||||
stackTrace: message.stackTrace(),
|
||||
text: message.text,
|
||||
type: message.type,
|
||||
});
|
||||
this.#onConsole(message);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @returns The page's main frame.
|
||||
* @remarks
|
||||
* Page is guaranteed to have a main frame which persists during navigations.
|
||||
*/
|
||||
mainFrame() {
|
||||
return this.#frameManager.mainFrame();
|
||||
}
|
||||
async setViewport(viewport) {
|
||||
const fromSurface = !process.env.DISABLE_FROM_SURFACE;
|
||||
const request = fromSurface
|
||||
? {
|
||||
mobile: false,
|
||||
width: viewport.width,
|
||||
height: viewport.height,
|
||||
deviceScaleFactor: viewport.deviceScaleFactor,
|
||||
screenOrientation: {
|
||||
angle: 0,
|
||||
type: 'portraitPrimary',
|
||||
},
|
||||
}
|
||||
: {
|
||||
mobile: false,
|
||||
width: viewport.width,
|
||||
height: viewport.height,
|
||||
deviceScaleFactor: 1,
|
||||
screenHeight: viewport.height,
|
||||
screenWidth: viewport.width,
|
||||
scale: viewport.deviceScaleFactor,
|
||||
viewport: {
|
||||
height: viewport.height * viewport.deviceScaleFactor,
|
||||
width: viewport.width * viewport.deviceScaleFactor,
|
||||
scale: 1,
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
};
|
||||
const { value } = await this.#client.send('Emulation.setDeviceMetricsOverride', request);
|
||||
return value;
|
||||
}
|
||||
setDefaultNavigationTimeout(timeout) {
|
||||
this.#timeoutSettings.setDefaultNavigationTimeout(timeout);
|
||||
}
|
||||
setDefaultTimeout(timeout) {
|
||||
this.#timeoutSettings.setDefaultTimeout(timeout);
|
||||
}
|
||||
async evaluateHandle(pageFunction, ...args) {
|
||||
const context = await this.mainFrame().executionContext();
|
||||
return context.evaluateHandle(pageFunction, ...args);
|
||||
}
|
||||
#onConsoleAPI(event) {
|
||||
if (event.executionContextId === 0) {
|
||||
return;
|
||||
}
|
||||
const context = this.#frameManager.executionContextById(event.executionContextId, this.#client);
|
||||
const values = event.args.map((arg) => {
|
||||
return (0, JSHandle_1._createJSHandle)(context, arg);
|
||||
});
|
||||
this.#addConsoleMessage(event.type, values, event.stackTrace);
|
||||
}
|
||||
async #onBindingCalled(event) {
|
||||
let payload;
|
||||
try {
|
||||
payload = JSON.parse(event.payload);
|
||||
}
|
||||
catch (_a) {
|
||||
// The binding was either called by something in the page or it was
|
||||
// called before our wrapper was initialized.
|
||||
return;
|
||||
}
|
||||
const { type, name, seq, args } = payload;
|
||||
if (type !== 'exposedFun' || !this.#pageBindings.has(name)) {
|
||||
return;
|
||||
}
|
||||
let expression = null;
|
||||
try {
|
||||
const pageBinding = this.#pageBindings.get(name);
|
||||
(0, assert_1.assert)(pageBinding);
|
||||
const result = await pageBinding(...args);
|
||||
expression = (0, util_1.pageBindingDeliverResultString)(name, seq, result);
|
||||
}
|
||||
catch (_error) {
|
||||
if ((0, util_1.isErrorLike)(_error)) {
|
||||
expression = (0, util_1.pageBindingDeliverErrorString)(name, seq, _error.message, _error.stack);
|
||||
}
|
||||
else {
|
||||
expression = (0, util_1.pageBindingDeliverErrorValueString)(name, seq, _error);
|
||||
}
|
||||
}
|
||||
await this.#client.send('Runtime.evaluate', {
|
||||
expression,
|
||||
contextId: event.executionContextId,
|
||||
});
|
||||
}
|
||||
#addConsoleMessage(eventType, args, stackTrace) {
|
||||
var _a, _b;
|
||||
const textTokens = [];
|
||||
for (const arg of args) {
|
||||
const remoteObject = arg._remoteObject;
|
||||
if (remoteObject.objectId) {
|
||||
textTokens.push(arg.toString());
|
||||
}
|
||||
else {
|
||||
textTokens.push((0, util_1.valueFromRemoteObject)(remoteObject));
|
||||
}
|
||||
}
|
||||
const stackTraceLocations = [];
|
||||
if (stackTrace) {
|
||||
for (const callFrame of stackTrace.callFrames) {
|
||||
stackTraceLocations.push({
|
||||
url: callFrame.url,
|
||||
lineNumber: callFrame.lineNumber,
|
||||
columnNumber: callFrame.columnNumber,
|
||||
});
|
||||
}
|
||||
}
|
||||
const { previewString, logLevelFromRemotionLog, logLevelFromEvent, tag } = format(eventType, (_a = args.map((a) => a._remoteObject)) !== null && _a !== void 0 ? _a : []);
|
||||
const logLevel = (_b = logLevelFromRemotionLog) !== null && _b !== void 0 ? _b : logLevelFromEvent;
|
||||
const message = new ConsoleMessage_1.ConsoleMessage({
|
||||
type: eventType,
|
||||
text: textTokens.join(' '),
|
||||
args,
|
||||
stackTraceLocations,
|
||||
previewString,
|
||||
logLevel,
|
||||
tag,
|
||||
});
|
||||
this.#onConsole(message);
|
||||
}
|
||||
url() {
|
||||
return this.mainFrame().url();
|
||||
}
|
||||
goto({ url, timeout, options = {}, }) {
|
||||
return this.#frameManager.mainFrame().goto(url, timeout, options);
|
||||
}
|
||||
async bringToFront() {
|
||||
await this.#client.send('Page.bringToFront');
|
||||
}
|
||||
async setAutoDarkModeOverride() {
|
||||
const result = await this.#client.send('Emulation.setEmulatedMedia', {
|
||||
media: 'screen',
|
||||
features: [
|
||||
{
|
||||
name: 'prefers-color-scheme',
|
||||
value: 'dark',
|
||||
},
|
||||
],
|
||||
});
|
||||
console.log(result);
|
||||
}
|
||||
evaluate(pageFunction, ...args) {
|
||||
return this.#frameManager.mainFrame().evaluate(pageFunction, ...args);
|
||||
}
|
||||
async evaluateOnNewDocument(pageFunction, ...args) {
|
||||
const source = (0, util_1.evaluationString)(pageFunction, ...args);
|
||||
await this.#client.send('Page.addScriptToEvaluateOnNewDocument', {
|
||||
source,
|
||||
});
|
||||
}
|
||||
async close(options = { runBeforeUnload: undefined }) {
|
||||
const connection = this.#client.connection();
|
||||
if (!connection) {
|
||||
return;
|
||||
}
|
||||
const runBeforeUnload = Boolean(options.runBeforeUnload);
|
||||
if (runBeforeUnload) {
|
||||
await this.#client.send('Page.close');
|
||||
}
|
||||
else {
|
||||
await connection.send('Target.closeTarget', {
|
||||
targetId: this.#target._targetId,
|
||||
});
|
||||
await this.#target._isClosedPromise;
|
||||
}
|
||||
}
|
||||
setBrowserSourceMapGetter(context) {
|
||||
this.sourceMapGetter = context;
|
||||
}
|
||||
}
|
||||
exports.Page = Page;
|
||||
Generated
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
import { Connection } from './Connection';
|
||||
export declare const makeBrowserRunner: ({ executablePath, processArguments, userDataDir, logLevel, indent, timeout, }: {
|
||||
executablePath: string;
|
||||
processArguments: string[];
|
||||
userDataDir: string;
|
||||
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
||||
indent: boolean;
|
||||
timeout: number;
|
||||
}) => Promise<{
|
||||
listeners: (() => import("./EventEmitter").CommonEventEmitter)[];
|
||||
deleteBrowserCaches: () => void;
|
||||
forgetEventLoop: () => void;
|
||||
rememberEventLoop: () => void;
|
||||
connection: Connection;
|
||||
closeProcess: () => Promise<void>;
|
||||
}>;
|
||||
export type BrowserRunner = Awaited<ReturnType<typeof makeBrowserRunner>>;
|
||||
Generated
Vendored
+303
@@ -0,0 +1,303 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2020 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 () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeBrowserRunner = void 0;
|
||||
const childProcess = __importStar(require("node:child_process"));
|
||||
const node_path_1 = require("node:path");
|
||||
const delete_directory_1 = require("../delete-directory");
|
||||
const log_level_1 = require("../log-level");
|
||||
const logger_1 = require("../logger");
|
||||
const truthy_1 = require("../truthy");
|
||||
const Connection_1 = require("./Connection");
|
||||
const Errors_1 = require("./Errors");
|
||||
const NodeWebSocketTransport_1 = require("./NodeWebSocketTransport");
|
||||
const assert_1 = require("./assert");
|
||||
const should_log_message_1 = require("./should-log-message");
|
||||
const util_1 = require("./util");
|
||||
const PROCESS_ERROR_EXPLANATION = `Puppeteer was unable to kill the process which ran the browser binary.
|
||||
This means that, on future Puppeteer launches, Puppeteer might not be able to launch the browser.
|
||||
Please check your open processes and ensure that the browser processes that Puppeteer launched have been killed.
|
||||
If you think this is a bug, please report it on the Puppeteer issue tracker.`;
|
||||
const makeBrowserRunner = async ({ executablePath, processArguments, userDataDir, logLevel, indent, timeout, }) => {
|
||||
var _a, _b;
|
||||
const dumpio = (0, log_level_1.isEqualOrBelowLogLevel)(logLevel, 'verbose');
|
||||
const stdio = dumpio
|
||||
? ['ignore', 'pipe', 'pipe']
|
||||
: ['pipe', 'pipe', 'pipe'];
|
||||
const proc = childProcess.spawn(executablePath, processArguments, {
|
||||
// On non-windows platforms, `detached: true` makes child process a
|
||||
// leader of a new process group, making it possible to kill child
|
||||
// process tree with `.kill(-pid)` command. @see
|
||||
// https://nodejs.org/api/child_process.html#child_process_options_detached
|
||||
detached: process.platform !== 'win32',
|
||||
env: process.env,
|
||||
stdio,
|
||||
});
|
||||
const browserWSEndpoint = await waitForWSEndpoint({
|
||||
browserProcess: proc,
|
||||
timeout,
|
||||
indent,
|
||||
logLevel,
|
||||
});
|
||||
const transport = await NodeWebSocketTransport_1.NodeWebSocketTransport.create(browserWSEndpoint);
|
||||
const connection = new Connection_1.Connection(transport);
|
||||
const killProcess = () => {
|
||||
// If the process failed to launch (for example if the browser executable path
|
||||
// is invalid), then the process does not get a pid assigned. A call to
|
||||
// `proc.kill` would error, as the `pid` to-be-killed can not be found.
|
||||
if (proc.pid && pidExists(proc.pid)) {
|
||||
try {
|
||||
if (process.platform === 'win32') {
|
||||
childProcess.exec(`taskkill /pid ${proc.pid} /T /F`, (error) => {
|
||||
if (error) {
|
||||
// taskkill can fail to kill the process e.g. due to missing permissions.
|
||||
// Let's kill the process via Node API. This delays killing of all child
|
||||
// processes of `this.proc` until the main Node.js process dies.
|
||||
proc.kill();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
// on linux the process group can be killed with the group id prefixed with
|
||||
// a minus sign. The process group id is the group leader's pid.
|
||||
const processGroupId = -proc.pid;
|
||||
logger_1.Log.verbose({ indent, logLevel }, `Trying to kill browser process group ${processGroupId}`);
|
||||
try {
|
||||
process.kill(processGroupId, 'SIGKILL');
|
||||
}
|
||||
catch (error) {
|
||||
// Killing the process group can fail due e.g. to missing permissions.
|
||||
// Let's kill the process via Node API. This delays killing of all child
|
||||
// processes of `this.proc` until the main Node.js process dies.
|
||||
logger_1.Log.verbose({ indent, logLevel }, `Could not kill browser process group ${processGroupId}. Killing process via Node.js API`);
|
||||
proc.kill('SIGKILL');
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
throw new Error(`${PROCESS_ERROR_EXPLANATION}\nError cause: ${(0, util_1.isErrorLike)(error) ? error.stack : error}`);
|
||||
}
|
||||
}
|
||||
(0, delete_directory_1.deleteDirectory)(userDataDir);
|
||||
// Cleanup this listener last, as that makes sure the full callback runs. If we
|
||||
// perform this earlier, then the previous function calls would not happen.
|
||||
(0, util_1.removeEventListeners)(listeners);
|
||||
};
|
||||
const closeProcess = () => {
|
||||
if (closed) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
logger_1.Log.verbose({ indent, logLevel }, 'Received SIGTERM signal. Killing browser process');
|
||||
killProcess();
|
||||
(0, delete_directory_1.deleteDirectory)(userDataDir);
|
||||
// Cleanup this listener last, as that makes sure the full callback runs. If we
|
||||
// perform this earlier, then the previous function calls would not happen.
|
||||
(0, util_1.removeEventListeners)(listeners);
|
||||
return processClosing;
|
||||
};
|
||||
if (dumpio) {
|
||||
(_a = proc.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (d) => {
|
||||
const message = d.toString('utf8').trim();
|
||||
if ((0, should_log_message_1.shouldLogBrowserMessage)(message)) {
|
||||
const formatted = (0, should_log_message_1.formatChromeMessage)(message);
|
||||
if (!formatted) {
|
||||
return;
|
||||
}
|
||||
const { output, tag } = formatted;
|
||||
logger_1.Log.verbose({ indent, logLevel, tag }, output);
|
||||
}
|
||||
});
|
||||
(_b = proc.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (d) => {
|
||||
const message = d.toString('utf8').trim();
|
||||
if ((0, should_log_message_1.shouldLogBrowserMessage)(message)) {
|
||||
const formatted = (0, should_log_message_1.formatChromeMessage)(message);
|
||||
if (!formatted) {
|
||||
return;
|
||||
}
|
||||
const { output, tag } = formatted;
|
||||
logger_1.Log.error({ indent, logLevel, tag }, output);
|
||||
}
|
||||
});
|
||||
}
|
||||
let closed = false;
|
||||
const processClosing = new Promise((fulfill, reject) => {
|
||||
proc.once('exit', () => {
|
||||
closed = true;
|
||||
// Cleanup as processes exit.
|
||||
try {
|
||||
fulfill();
|
||||
}
|
||||
catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
});
|
||||
const listeners = [(0, util_1.addEventListener)(process, 'exit', killProcess)];
|
||||
listeners.push((0, util_1.addEventListener)(process, 'SIGINT', () => {
|
||||
killProcess();
|
||||
process.exit(130);
|
||||
}));
|
||||
listeners.push((0, util_1.addEventListener)(process, 'SIGTERM', closeProcess));
|
||||
listeners.push((0, util_1.addEventListener)(process, 'SIGHUP', closeProcess));
|
||||
const deleteBrowserCaches = () => {
|
||||
// We leave some data:
|
||||
// Default/Cookies
|
||||
// Default/Local Storage
|
||||
// Default/Session Storage
|
||||
// DevToolsActivePort
|
||||
// Because not sure if it is bad to delete them while Chrome is running.
|
||||
const cachePaths = [
|
||||
(0, node_path_1.join)(userDataDir, 'Default', 'Cache', 'Cache_Data'),
|
||||
(0, node_path_1.join)(userDataDir, 'Default', 'Code Cache'),
|
||||
(0, node_path_1.join)(userDataDir, 'Default', 'DawnCache'),
|
||||
(0, node_path_1.join)(userDataDir, 'Default', 'GPUCache'),
|
||||
];
|
||||
for (const p of cachePaths) {
|
||||
(0, delete_directory_1.deleteDirectory)(p);
|
||||
}
|
||||
};
|
||||
const rememberEventLoop = () => {
|
||||
var _a, _b;
|
||||
proc.ref();
|
||||
// @ts-expect-error
|
||||
(_a = proc.stdout) === null || _a === void 0 ? void 0 : _a.ref();
|
||||
// @ts-expect-error
|
||||
(_b = proc.stderr) === null || _b === void 0 ? void 0 : _b.ref();
|
||||
(0, assert_1.assert)(connection, 'BrowserRunner not connected.');
|
||||
connection.transport.rememberEventLoop();
|
||||
};
|
||||
const forgetEventLoop = () => {
|
||||
var _a, _b;
|
||||
proc.unref();
|
||||
// @ts-expect-error
|
||||
(_a = proc.stdout) === null || _a === void 0 ? void 0 : _a.unref();
|
||||
// @ts-expect-error
|
||||
(_b = proc.stderr) === null || _b === void 0 ? void 0 : _b.unref();
|
||||
(0, assert_1.assert)(connection, 'BrowserRunner not connected.');
|
||||
connection.transport.forgetEventLoop();
|
||||
};
|
||||
return {
|
||||
listeners,
|
||||
deleteBrowserCaches,
|
||||
forgetEventLoop,
|
||||
rememberEventLoop,
|
||||
connection,
|
||||
closeProcess,
|
||||
};
|
||||
};
|
||||
exports.makeBrowserRunner = makeBrowserRunner;
|
||||
function waitForWSEndpoint({ browserProcess, timeout, logLevel, indent, }) {
|
||||
const browserStderr = browserProcess.stderr;
|
||||
const browserStdout = browserProcess.stdout;
|
||||
(0, assert_1.assert)(browserStderr, '`browserProcess` does not have stderr.');
|
||||
(0, assert_1.assert)(browserStdout, '`browserProcess` does not have stdout.');
|
||||
let stdioString = '';
|
||||
return new Promise((resolve, reject) => {
|
||||
browserStderr.addListener('data', onStdIoData);
|
||||
browserStdout.addListener('data', onStdIoData);
|
||||
browserStderr.addListener('close', onClose);
|
||||
const listeners = [
|
||||
() => browserStderr.removeListener('data', onStdIoData),
|
||||
() => browserStdout.removeListener('data', onStdIoData),
|
||||
() => browserStderr.removeListener('close', onClose),
|
||||
(0, util_1.addEventListener)(browserProcess, 'exit', (code, signal) => {
|
||||
logger_1.Log.verbose({ indent, logLevel }, 'Browser process exited with code', code, 'signal', signal);
|
||||
return onClose(new Error(`Closed with ${code} signal: ${signal}`));
|
||||
}),
|
||||
(0, util_1.addEventListener)(browserProcess, 'error', (error) => {
|
||||
return onClose(error);
|
||||
}),
|
||||
];
|
||||
const timeoutId = timeout ? setTimeout(onTimeout, timeout) : 0;
|
||||
function onClose(error) {
|
||||
cleanup();
|
||||
reject(new Error([
|
||||
'Failed to launch the browser process!',
|
||||
error ? error.stack : null,
|
||||
stdioString,
|
||||
'Troubleshooting: https://remotion.dev/docs/troubleshooting/browser-launch',
|
||||
]
|
||||
.filter(truthy_1.truthy)
|
||||
.join('\n')));
|
||||
}
|
||||
function onTimeout() {
|
||||
cleanup();
|
||||
reject(new Errors_1.TimeoutError(`Timed out after ${timeout} ms while trying to connect to the browser! Chrome logged the following: ${stdioString}`));
|
||||
}
|
||||
function onStdIoData(data) {
|
||||
stdioString += data.toString('utf8');
|
||||
const match = stdioString.match(/DevTools listening on (ws:\/\/.*)/);
|
||||
if (!match) {
|
||||
return;
|
||||
}
|
||||
cleanup();
|
||||
resolve(match[1]);
|
||||
}
|
||||
function cleanup() {
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
(0, util_1.removeEventListeners)(listeners);
|
||||
}
|
||||
});
|
||||
}
|
||||
function pidExists(pid) {
|
||||
try {
|
||||
return process.kill(pid, 0);
|
||||
}
|
||||
catch (error) {
|
||||
if ((0, util_1.isErrnoException)(error)) {
|
||||
if (error.code && error.code === 'ESRCH') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+49
@@ -0,0 +1,49 @@
|
||||
import type { Commands } from './devtools-commands';
|
||||
import type { TargetInfo } from './devtools-types';
|
||||
import { EventEmitter } from './EventEmitter';
|
||||
import type { NodeWebSocketTransport } from './NodeWebSocketTransport';
|
||||
export declare class Connection extends EventEmitter {
|
||||
#private;
|
||||
transport: NodeWebSocketTransport;
|
||||
constructor(transport: NodeWebSocketTransport);
|
||||
static fromSession(session: CDPSession): Connection | undefined;
|
||||
session(sessionId: string): CDPSession | null;
|
||||
send<T extends keyof Commands>(method: T, ...paramArgs: Commands[T]['paramsType']): Promise<{
|
||||
value: Commands[T]['returnType'];
|
||||
size: number;
|
||||
}>;
|
||||
_rawSend(message: Record<string, unknown>): number;
|
||||
dispose(): void;
|
||||
/**
|
||||
* @param targetInfo - The target info
|
||||
* @returns The CDP session that is created
|
||||
*/
|
||||
createSession(targetInfo: TargetInfo): Promise<CDPSession>;
|
||||
}
|
||||
interface CDPSessionOnMessageObject {
|
||||
id?: number;
|
||||
method: string;
|
||||
params: Record<string, unknown>;
|
||||
error: {
|
||||
message: string;
|
||||
data: any;
|
||||
code: number;
|
||||
};
|
||||
result?: any;
|
||||
}
|
||||
export declare const CDPSessionEmittedEvents: {
|
||||
readonly Disconnected: symbol;
|
||||
};
|
||||
export declare class CDPSession extends EventEmitter {
|
||||
#private;
|
||||
constructor(connection: Connection, targetType: string, sessionId: string);
|
||||
connection(): Connection | undefined;
|
||||
send<T extends keyof Commands>(method: T, ...paramArgs: Commands[T]['paramsType']): Promise<{
|
||||
value: Commands[T]['returnType'];
|
||||
size: number;
|
||||
}>;
|
||||
_onMessage(object: CDPSessionOnMessageObject, size: number): void;
|
||||
_onClosed(): void;
|
||||
id(): string;
|
||||
}
|
||||
export {};
|
||||
Generated
Vendored
+245
@@ -0,0 +1,245 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CDPSession = exports.CDPSessionEmittedEvents = exports.Connection = void 0;
|
||||
/**
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
const logger_1 = require("../logger");
|
||||
const Errors_1 = require("./Errors");
|
||||
const EventEmitter_1 = require("./EventEmitter");
|
||||
const ConnectionEmittedEvents = {
|
||||
Disconnected: Symbol('Connection.Disconnected'),
|
||||
};
|
||||
class Connection extends EventEmitter_1.EventEmitter {
|
||||
transport;
|
||||
#lastId = 0;
|
||||
#sessions = new Map();
|
||||
#closed = false;
|
||||
#callbacks = new Map();
|
||||
constructor(transport) {
|
||||
super();
|
||||
this.transport = transport;
|
||||
this.transport.onmessage = this.#onMessage.bind(this);
|
||||
this.transport.onclose = this.#onClose.bind(this);
|
||||
}
|
||||
static fromSession(session) {
|
||||
return session.connection();
|
||||
}
|
||||
session(sessionId) {
|
||||
return this.#sessions.get(sessionId) || null;
|
||||
}
|
||||
send(method, ...paramArgs) {
|
||||
// There is only ever 1 param arg passed, but the Protocol defines it as an
|
||||
// array of 0 or 1 items See this comment:
|
||||
// https://github.com/ChromeDevTools/devtools-protocol/pull/113#issuecomment-412603285
|
||||
// which explains why the protocol defines the params this way for better
|
||||
// type-inference.
|
||||
// So now we check if there are any params or not and deal with them accordingly.
|
||||
const params = paramArgs.length ? paramArgs[0] : undefined;
|
||||
const id = this._rawSend({ method, params });
|
||||
return new Promise((resolve, reject) => {
|
||||
var _a;
|
||||
this.#callbacks.set(id, {
|
||||
resolve,
|
||||
reject,
|
||||
method,
|
||||
returnSize: true,
|
||||
stack: (_a = new Error().stack) !== null && _a !== void 0 ? _a : '',
|
||||
fn: method + JSON.stringify(params),
|
||||
});
|
||||
});
|
||||
}
|
||||
_rawSend(message) {
|
||||
const id = ++this.#lastId;
|
||||
const stringifiedMessage = JSON.stringify({ ...message, id });
|
||||
this.transport.send(stringifiedMessage);
|
||||
return id;
|
||||
}
|
||||
#onMessage(message) {
|
||||
const object = JSON.parse(message);
|
||||
if (object.method === 'Target.attachedToTarget') {
|
||||
const { sessionId } = object.params;
|
||||
const session = new CDPSession(this, object.params.targetInfo.type, sessionId);
|
||||
this.#sessions.set(sessionId, session);
|
||||
this.emit('sessionattached', session);
|
||||
const parentSession = this.#sessions.get(object.sessionId);
|
||||
if (parentSession) {
|
||||
parentSession.emit('sessionattached', session);
|
||||
}
|
||||
}
|
||||
else if (object.method === 'Target.detachedFromTarget') {
|
||||
const session = this.#sessions.get(object.params.sessionId);
|
||||
if (session) {
|
||||
session._onClosed();
|
||||
this.#sessions.delete(object.params.sessionId);
|
||||
this.emit('sessiondetached', session);
|
||||
const parentSession = this.#sessions.get(object.sessionId);
|
||||
if (parentSession) {
|
||||
parentSession.emit('sessiondetached', session);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (object.sessionId) {
|
||||
const session = this.#sessions.get(object.sessionId);
|
||||
if (session) {
|
||||
session._onMessage(object, message.length);
|
||||
}
|
||||
}
|
||||
else if (object.id) {
|
||||
const callback = this.#callbacks.get(object.id);
|
||||
// Callbacks could be all rejected if someone has called `.dispose()`.
|
||||
if (callback) {
|
||||
this.#callbacks.delete(object.id);
|
||||
if (object.error) {
|
||||
callback.reject(createProtocolError(callback.method, object));
|
||||
}
|
||||
else if (callback.returnSize) {
|
||||
callback.resolve({ value: object.result, size: message.length });
|
||||
}
|
||||
else {
|
||||
callback.resolve(object.result);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.emit(object.method, object.params);
|
||||
}
|
||||
}
|
||||
#onClose() {
|
||||
if (this.#closed) {
|
||||
return;
|
||||
}
|
||||
this.transport.onmessage = undefined;
|
||||
this.transport.onclose = undefined;
|
||||
for (const callback of this.#callbacks.values()) {
|
||||
callback.reject(rewriteError(new Errors_1.ProtocolError(), `Protocol error (${callback.method}): Target closed. https://www.remotion.dev/docs/target-closed`));
|
||||
}
|
||||
this.#callbacks.clear();
|
||||
for (const session of this.#sessions.values()) {
|
||||
session._onClosed();
|
||||
}
|
||||
this.#sessions.clear();
|
||||
this.emit(ConnectionEmittedEvents.Disconnected);
|
||||
}
|
||||
dispose() {
|
||||
this.#onClose();
|
||||
this.transport.close();
|
||||
}
|
||||
/**
|
||||
* @param targetInfo - The target info
|
||||
* @returns The CDP session that is created
|
||||
*/
|
||||
async createSession(targetInfo) {
|
||||
const { value: { sessionId }, } = await this.send('Target.attachToTarget', {
|
||||
targetId: targetInfo.targetId,
|
||||
flatten: true,
|
||||
});
|
||||
const session = this.#sessions.get(sessionId);
|
||||
if (!session) {
|
||||
throw new Error('CDPSession creation failed.');
|
||||
}
|
||||
return session;
|
||||
}
|
||||
}
|
||||
exports.Connection = Connection;
|
||||
exports.CDPSessionEmittedEvents = {
|
||||
Disconnected: Symbol('CDPSession.Disconnected'),
|
||||
};
|
||||
class CDPSession extends EventEmitter_1.EventEmitter {
|
||||
#sessionId;
|
||||
#targetType;
|
||||
#callbacks = new Map();
|
||||
#connection;
|
||||
constructor(connection, targetType, sessionId) {
|
||||
super();
|
||||
this.#connection = connection;
|
||||
this.#targetType = targetType;
|
||||
this.#sessionId = sessionId;
|
||||
}
|
||||
connection() {
|
||||
return this.#connection;
|
||||
}
|
||||
send(method, ...paramArgs) {
|
||||
if (!this.#connection) {
|
||||
return Promise.reject(new Error(`Protocol error (${method}): Session closed. Most likely the ${this.#targetType} has been closed.`));
|
||||
}
|
||||
// See the comment in Connection#send explaining why we do this.
|
||||
const params = paramArgs.length ? paramArgs[0] : undefined;
|
||||
const id = this.#connection._rawSend({
|
||||
sessionId: this.#sessionId,
|
||||
method,
|
||||
params,
|
||||
});
|
||||
return new Promise((resolve, reject) => {
|
||||
var _a;
|
||||
if (this.#callbacks.size > 100) {
|
||||
for (const callback of this.#callbacks.values()) {
|
||||
logger_1.Log.info({ indent: false, logLevel: 'info' }, callback.fn);
|
||||
}
|
||||
throw new Error('Leak detected: Too many callbacks');
|
||||
}
|
||||
this.#callbacks.set(id, {
|
||||
resolve,
|
||||
reject,
|
||||
method,
|
||||
returnSize: true,
|
||||
stack: (_a = new Error().stack) !== null && _a !== void 0 ? _a : '',
|
||||
fn: method + JSON.stringify(params),
|
||||
});
|
||||
});
|
||||
}
|
||||
_onMessage(object, size) {
|
||||
const callback = object.id ? this.#callbacks.get(object.id) : undefined;
|
||||
if (object.id && callback) {
|
||||
this.#callbacks.delete(object.id);
|
||||
if (object.error) {
|
||||
callback.reject(createProtocolError(callback.method, object));
|
||||
}
|
||||
else if (callback.returnSize) {
|
||||
callback.resolve({ value: object.result, size });
|
||||
}
|
||||
else {
|
||||
callback.resolve(object.result);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.emit(object.method, object.params);
|
||||
}
|
||||
}
|
||||
_onClosed() {
|
||||
this.#connection = undefined;
|
||||
for (const callback of this.#callbacks.values()) {
|
||||
callback.reject(rewriteError(new Errors_1.ProtocolError(), `Protocol error (${callback.method}): Target closed. https://www.remotion.dev/docs/target-closed`));
|
||||
}
|
||||
this.#callbacks.clear();
|
||||
this.emit(exports.CDPSessionEmittedEvents.Disconnected);
|
||||
}
|
||||
id() {
|
||||
return this.#sessionId;
|
||||
}
|
||||
}
|
||||
exports.CDPSession = CDPSession;
|
||||
function createProtocolError(method, object) {
|
||||
let message = `Protocol error (${method}): ${object.error.message}`;
|
||||
if ('data' in object.error) {
|
||||
message += ` ${object.error.data}`;
|
||||
}
|
||||
return rewriteError(new Errors_1.ProtocolError(), message, object.error.message);
|
||||
}
|
||||
function rewriteError(error, message, originalMessage) {
|
||||
error.message = message;
|
||||
error.originalMessage = originalMessage !== null && originalMessage !== void 0 ? originalMessage : error.originalMessage;
|
||||
return error;
|
||||
}
|
||||
Generated
Vendored
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
import { LogLevel } from 'remotion';
|
||||
import type { JSHandle } from './JSHandle';
|
||||
export interface ConsoleMessageLocation {
|
||||
url?: string;
|
||||
lineNumber?: number;
|
||||
columnNumber?: number;
|
||||
}
|
||||
export type ConsoleMessageType = 'log' | 'debug' | 'info' | 'error' | 'warning' | 'dir' | 'dirxml' | 'table' | 'trace' | 'clear' | 'startGroup' | 'startGroupCollapsed' | 'endGroup' | 'assert' | 'profile' | 'profileEnd' | 'count' | 'timeEnd' | 'verbose';
|
||||
export declare class ConsoleMessage {
|
||||
#private;
|
||||
type: ConsoleMessageType;
|
||||
text: string;
|
||||
args: JSHandle[];
|
||||
previewString: string;
|
||||
logLevel: LogLevel;
|
||||
tag: string | null;
|
||||
constructor({ type, text, args, stackTraceLocations, previewString, logLevel, tag }: {
|
||||
type: ConsoleMessageType;
|
||||
text: string;
|
||||
args: JSHandle[];
|
||||
stackTraceLocations: ConsoleMessageLocation[];
|
||||
previewString: string;
|
||||
logLevel: LogLevel;
|
||||
tag: string | null;
|
||||
});
|
||||
stackTrace(): ConsoleMessageLocation[];
|
||||
}
|
||||
Generated
Vendored
+40
@@ -0,0 +1,40 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ConsoleMessage = void 0;
|
||||
class ConsoleMessage {
|
||||
type;
|
||||
text;
|
||||
args;
|
||||
previewString;
|
||||
#stackTraceLocations;
|
||||
logLevel;
|
||||
tag;
|
||||
constructor({ type, text, args, stackTraceLocations, previewString, logLevel, tag, }) {
|
||||
this.type = type;
|
||||
this.text = text;
|
||||
this.args = args;
|
||||
this.previewString = previewString;
|
||||
this.#stackTraceLocations = stackTraceLocations;
|
||||
this.logLevel = logLevel;
|
||||
this.tag = tag;
|
||||
}
|
||||
stackTrace() {
|
||||
return this.#stackTraceLocations;
|
||||
}
|
||||
}
|
||||
exports.ConsoleMessage = ConsoleMessage;
|
||||
Generated
Vendored
+56
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
import type { HeadlessBrowser } from './Browser';
|
||||
import type { EvaluateFn, EvaluateFnReturnType, EvaluateHandleFn, SerializableOrJSHandle, UnwrapPromiseLike } from './EvalTypes';
|
||||
import type { ExecutionContext } from './ExecutionContext';
|
||||
import type { Frame } from './FrameManager';
|
||||
import type { JSHandle } from './JSHandle';
|
||||
export declare class DOMWorld {
|
||||
#private;
|
||||
get _waitTasks(): Set<WaitTask>;
|
||||
constructor(frame: Frame);
|
||||
frame(): Frame;
|
||||
_setContext(context: ExecutionContext | null): void;
|
||||
_hasContext(): boolean;
|
||||
_detach(): void;
|
||||
executionContext(): Promise<ExecutionContext>;
|
||||
evaluateHandle<HandlerType extends JSHandle = JSHandle>(pageFunction: EvaluateHandleFn, ...args: SerializableOrJSHandle[]): Promise<HandlerType>;
|
||||
evaluate<T extends EvaluateFn>(pageFunction: T, ...args: SerializableOrJSHandle[]): Promise<UnwrapPromiseLike<EvaluateFnReturnType<T>>>;
|
||||
waitForFunction({ browser, timeout, pageFunction, title }: {
|
||||
browser: HeadlessBrowser;
|
||||
timeout: number | null;
|
||||
pageFunction: Function | string;
|
||||
title: string;
|
||||
}): WaitTask;
|
||||
}
|
||||
interface WaitTaskOptions {
|
||||
domWorld: DOMWorld;
|
||||
predicateBody: Function | string;
|
||||
title: string;
|
||||
timeout: number | null;
|
||||
browser: HeadlessBrowser;
|
||||
args: SerializableOrJSHandle[];
|
||||
}
|
||||
declare class WaitTask {
|
||||
#private;
|
||||
promise: Promise<JSHandle>;
|
||||
constructor(options: WaitTaskOptions);
|
||||
onBrowserClose: () => void;
|
||||
onBrowserCloseSilent: () => void;
|
||||
terminate(error: Error | null): void;
|
||||
rerun(): Promise<void>;
|
||||
}
|
||||
export {};
|
||||
Generated
Vendored
+258
@@ -0,0 +1,258 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DOMWorld = void 0;
|
||||
const assert_1 = require("./assert");
|
||||
const Errors_1 = require("./Errors");
|
||||
const util_1 = require("./util");
|
||||
class DOMWorld {
|
||||
#frame;
|
||||
#contextPromise = null;
|
||||
#contextResolveCallback = null;
|
||||
#detached = false;
|
||||
#waitTasks = new Set();
|
||||
get _waitTasks() {
|
||||
return this.#waitTasks;
|
||||
}
|
||||
constructor(frame) {
|
||||
// Keep own reference to client because it might differ from the FrameManager's
|
||||
// client for OOP iframes.
|
||||
this.#frame = frame;
|
||||
this._setContext(null);
|
||||
}
|
||||
frame() {
|
||||
return this.#frame;
|
||||
}
|
||||
_setContext(context) {
|
||||
var _a;
|
||||
if (context) {
|
||||
(0, assert_1.assert)(this.#contextResolveCallback, 'Execution Context has already been set.');
|
||||
(_a = this.#contextResolveCallback) === null || _a === void 0 ? void 0 : _a.call(null, context);
|
||||
this.#contextResolveCallback = null;
|
||||
for (const waitTask of this._waitTasks) {
|
||||
waitTask.rerun();
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.#contextPromise = new Promise((fulfill) => {
|
||||
this.#contextResolveCallback = fulfill;
|
||||
});
|
||||
}
|
||||
}
|
||||
_hasContext() {
|
||||
return !this.#contextResolveCallback;
|
||||
}
|
||||
_detach() {
|
||||
this.#detached = true;
|
||||
for (const waitTask of this._waitTasks) {
|
||||
waitTask.terminate(new Error('waitForFunction failed: frame got detached.'));
|
||||
}
|
||||
}
|
||||
executionContext() {
|
||||
if (this.#detached) {
|
||||
throw new Error(`Execution context is not available in detached frame "${this.#frame.url()}" (are you trying to evaluate?)`);
|
||||
}
|
||||
if (this.#contextPromise === null) {
|
||||
throw new Error(`Execution content promise is missing`);
|
||||
}
|
||||
return this.#contextPromise;
|
||||
}
|
||||
async evaluateHandle(pageFunction, ...args) {
|
||||
const context = await this.executionContext();
|
||||
return context.evaluateHandle(pageFunction, ...args);
|
||||
}
|
||||
async evaluate(pageFunction, ...args) {
|
||||
const context = await this.executionContext();
|
||||
return context.evaluate(pageFunction, ...args);
|
||||
}
|
||||
waitForFunction({ browser, timeout, pageFunction, title, }) {
|
||||
return new WaitTask({
|
||||
domWorld: this,
|
||||
predicateBody: pageFunction,
|
||||
title,
|
||||
timeout,
|
||||
args: [],
|
||||
browser,
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.DOMWorld = DOMWorld;
|
||||
const noop = () => undefined;
|
||||
class WaitTask {
|
||||
#domWorld;
|
||||
#timeout;
|
||||
#predicateBody;
|
||||
#args;
|
||||
#runCount = 0;
|
||||
#resolve = noop;
|
||||
#reject = noop;
|
||||
#timeoutTimer;
|
||||
#terminated = false;
|
||||
#browser;
|
||||
promise;
|
||||
constructor(options) {
|
||||
function getPredicateBody(predicateBody) {
|
||||
if ((0, util_1.isString)(predicateBody)) {
|
||||
return `return (${predicateBody});`;
|
||||
}
|
||||
return `return (${predicateBody})(...args);`;
|
||||
}
|
||||
this.#domWorld = options.domWorld;
|
||||
this.#timeout = options.timeout;
|
||||
this.#predicateBody = getPredicateBody(options.predicateBody);
|
||||
this.#args = options.args;
|
||||
this.#runCount = 0;
|
||||
this.#domWorld._waitTasks.add(this);
|
||||
this.promise = new Promise((resolve, reject) => {
|
||||
this.#resolve = resolve;
|
||||
this.#reject = reject;
|
||||
});
|
||||
// Since page navigation requires us to re-install the pageScript, we should track
|
||||
// timeout on our end.
|
||||
if (options.timeout) {
|
||||
const timeoutError = new Errors_1.TimeoutError(`waiting for ${options.title} failed: timeout ${options.timeout}ms exceeded`);
|
||||
this.#timeoutTimer = setTimeout(() => {
|
||||
return this.#reject(timeoutError);
|
||||
}, options.timeout);
|
||||
}
|
||||
this.#browser = options.browser;
|
||||
this.#browser.on("closed" /* BrowserEmittedEvents.Closed */, this.onBrowserClose);
|
||||
this.#browser.on("closed-silent" /* BrowserEmittedEvents.ClosedSilent */, this.onBrowserCloseSilent);
|
||||
this.rerun();
|
||||
}
|
||||
onBrowserClose = () => {
|
||||
return this.terminate(new Error('Browser was closed'));
|
||||
};
|
||||
onBrowserCloseSilent = () => {
|
||||
return this.terminate(null);
|
||||
};
|
||||
terminate(error) {
|
||||
this.#terminated = true;
|
||||
if (error) {
|
||||
this.#reject(error);
|
||||
}
|
||||
this.#cleanup();
|
||||
}
|
||||
async rerun() {
|
||||
const runCount = ++this.#runCount;
|
||||
let success = null;
|
||||
let error = null;
|
||||
const context = await this.#domWorld.executionContext();
|
||||
if (this.#terminated || runCount !== this.#runCount) {
|
||||
return;
|
||||
}
|
||||
if (this.#terminated || runCount !== this.#runCount) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
success = await context.evaluateHandle(waitForPredicatePageFunction, this.#predicateBody, this.#timeout, ...this.#args);
|
||||
}
|
||||
catch (error_) {
|
||||
error = error_;
|
||||
}
|
||||
if (this.#terminated || runCount !== this.#runCount) {
|
||||
if (success) {
|
||||
await success.dispose();
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Ignore timeouts in pageScript - we track timeouts ourselves.
|
||||
// If the frame's execution context has already changed, `frame.evaluate` will
|
||||
// throw an error - ignore this predicate run altogether.
|
||||
if (!error &&
|
||||
(await this.#domWorld
|
||||
.evaluate((s) => {
|
||||
return !s;
|
||||
}, success)
|
||||
.catch(() => {
|
||||
return true;
|
||||
}))) {
|
||||
if (!success) {
|
||||
throw new Error('Assertion: result handle is not available');
|
||||
}
|
||||
await success.dispose();
|
||||
return;
|
||||
}
|
||||
if (error) {
|
||||
if (error.message.includes('TypeError: binding is not a function')) {
|
||||
return this.rerun();
|
||||
}
|
||||
// When frame is detached the task should have been terminated by the DOMWorld.
|
||||
// This can fail if we were adding this task while the frame was detached,
|
||||
// so we terminate here instead.
|
||||
if (error.message.includes('Execution context is not available in detached frame')) {
|
||||
this.terminate(new Error('waitForFunction failed: frame got detached.'));
|
||||
return;
|
||||
}
|
||||
// When the page is navigated, the promise is rejected.
|
||||
// We will try again in the new execution context.
|
||||
if (error.message.includes('Execution context was destroyed')) {
|
||||
return;
|
||||
}
|
||||
// We could have tried to evaluate in a context which was already
|
||||
// destroyed.
|
||||
if (error.message.includes('Cannot find context with specified id')) {
|
||||
return;
|
||||
}
|
||||
this.#reject(error);
|
||||
}
|
||||
else {
|
||||
if (!success) {
|
||||
throw new Error('Assertion: result handle is not available');
|
||||
}
|
||||
this.#resolve(success);
|
||||
}
|
||||
this.#cleanup();
|
||||
}
|
||||
#cleanup() {
|
||||
if (this.#timeoutTimer !== undefined) {
|
||||
clearTimeout(this.#timeoutTimer);
|
||||
}
|
||||
this.#browser.off("closed" /* BrowserEmittedEvents.Closed */, this.onBrowserClose);
|
||||
this.#browser.off("closed-silent" /* BrowserEmittedEvents.ClosedSilent */, this.onBrowserCloseSilent);
|
||||
if (this.#domWorld._waitTasks.size > 100) {
|
||||
throw new Error('Leak detected: Too many WaitTasks');
|
||||
}
|
||||
this.#domWorld._waitTasks.delete(this);
|
||||
}
|
||||
}
|
||||
function waitForPredicatePageFunction(predicateBody, timeout, ...args) {
|
||||
// eslint-disable-next-line no-new-func
|
||||
const predicate = new Function('...args', predicateBody);
|
||||
let timedOut = false;
|
||||
if (timeout) {
|
||||
setTimeout(() => {
|
||||
timedOut = true;
|
||||
}, timeout);
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
async function onRaf() {
|
||||
if (timedOut) {
|
||||
resolve(undefined);
|
||||
return;
|
||||
}
|
||||
const success = await predicate(...args);
|
||||
if (success) {
|
||||
resolve(success);
|
||||
}
|
||||
else {
|
||||
requestAnimationFrame(onRaf);
|
||||
}
|
||||
}
|
||||
onRaf();
|
||||
});
|
||||
}
|
||||
Generated
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright 2018 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.
|
||||
*/
|
||||
declare class CustomError extends Error {
|
||||
constructor(message?: string);
|
||||
}
|
||||
export declare class TimeoutError extends CustomError {
|
||||
}
|
||||
export declare class ProtocolError extends CustomError {
|
||||
code?: number;
|
||||
originalMessage: string;
|
||||
}
|
||||
export {};
|
||||
Generated
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2018 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ProtocolError = exports.TimeoutError = void 0;
|
||||
class CustomError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = this.constructor.name;
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
}
|
||||
class TimeoutError extends CustomError {
|
||||
}
|
||||
exports.TimeoutError = TimeoutError;
|
||||
class ProtocolError extends CustomError {
|
||||
code;
|
||||
originalMessage = '';
|
||||
}
|
||||
exports.ProtocolError = ProtocolError;
|
||||
Generated
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
import type { JSHandle } from './JSHandle';
|
||||
export type EvaluateFn<T = any, U = any, V = any> = string | ((arg1: T, ...args: U[]) => V);
|
||||
export type UnwrapPromiseLike<T> = T extends PromiseLike<infer U> ? U : T;
|
||||
export type EvaluateFnReturnType<T extends EvaluateFn> = T extends (...args: any[]) => infer R ? R : any;
|
||||
export type EvaluateHandleFn = string | ((...args: any[]) => any);
|
||||
type Serializable = number | string | boolean | null | bigint | JSONArray | JSONObject;
|
||||
type JSONArray = readonly Serializable[];
|
||||
interface JSONObject {
|
||||
[key: string]: Serializable;
|
||||
}
|
||||
export type SerializableOrJSHandle = Serializable | JSHandle;
|
||||
export {};
|
||||
Generated
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
Generated
Vendored
+23
@@ -0,0 +1,23 @@
|
||||
import type { EventType, Handler } from './mitt';
|
||||
export interface CommonEventEmitter {
|
||||
on(event: EventType, handler: Handler): CommonEventEmitter;
|
||||
off(event: EventType, handler: Handler): CommonEventEmitter;
|
||||
addListener(event: EventType, handler: Handler): CommonEventEmitter;
|
||||
emit(event: EventType, eventData?: unknown): boolean;
|
||||
once(event: EventType, handler: Handler): CommonEventEmitter;
|
||||
listenerCount(event: string): number;
|
||||
removeAllListeners(event?: EventType): CommonEventEmitter;
|
||||
}
|
||||
export declare class EventEmitter implements CommonEventEmitter {
|
||||
private emitter;
|
||||
private eventsMap;
|
||||
constructor();
|
||||
on(event: EventType, handler: Handler): EventEmitter;
|
||||
off(event: EventType, handler: Handler): EventEmitter;
|
||||
addListener(event: EventType, handler: Handler): EventEmitter;
|
||||
emit(event: EventType, eventData?: unknown): boolean;
|
||||
once(event: EventType, handler: Handler): EventEmitter;
|
||||
listenerCount(event: EventType): number;
|
||||
removeAllListeners(event?: EventType): EventEmitter;
|
||||
private eventListenersCount;
|
||||
}
|
||||
Generated
Vendored
+54
@@ -0,0 +1,54 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.EventEmitter = void 0;
|
||||
const mitt_1 = __importDefault(require("./mitt"));
|
||||
class EventEmitter {
|
||||
emitter;
|
||||
eventsMap = new Map();
|
||||
constructor() {
|
||||
this.emitter = (0, mitt_1.default)(this.eventsMap);
|
||||
}
|
||||
on(event, handler) {
|
||||
this.emitter.on(event, handler);
|
||||
return this;
|
||||
}
|
||||
off(event, handler) {
|
||||
this.emitter.off(event, handler);
|
||||
return this;
|
||||
}
|
||||
addListener(event, handler) {
|
||||
this.on(event, handler);
|
||||
return this;
|
||||
}
|
||||
emit(event, eventData) {
|
||||
this.emitter.emit(event, eventData);
|
||||
return this.eventListenersCount(event) > 0;
|
||||
}
|
||||
once(event, handler) {
|
||||
const onceHandler = (eventData) => {
|
||||
handler(eventData);
|
||||
this.off(event, onceHandler);
|
||||
};
|
||||
return this.on(event, onceHandler);
|
||||
}
|
||||
listenerCount(event) {
|
||||
return this.eventListenersCount(event);
|
||||
}
|
||||
removeAllListeners(event) {
|
||||
if (event) {
|
||||
this.eventsMap.delete(event);
|
||||
}
|
||||
else {
|
||||
this.eventsMap.clear();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
eventListenersCount(event) {
|
||||
var _a;
|
||||
return ((_a = this.eventsMap.get(event)) === null || _a === void 0 ? void 0 : _a.length) || 0;
|
||||
}
|
||||
}
|
||||
exports.EventEmitter = EventEmitter;
|
||||
Generated
Vendored
+34
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
import type { CDPSession } from './Connection';
|
||||
import type { ExecutionContextDescription } from './devtools-types';
|
||||
import type { DOMWorld } from './DOMWorld';
|
||||
import type { EvaluateHandleFn, SerializableOrJSHandle } from './EvalTypes';
|
||||
import type { Frame } from './FrameManager';
|
||||
import type { ElementHandle } from './JSHandle';
|
||||
import { JSHandle } from './JSHandle';
|
||||
export declare const EVALUATION_SCRIPT_URL = "pptr://__puppeteer_evaluation_script__";
|
||||
export declare class ExecutionContext {
|
||||
#private;
|
||||
_client: CDPSession;
|
||||
_world: DOMWorld;
|
||||
_contextId: number;
|
||||
_contextName: string;
|
||||
constructor(client: CDPSession, contextPayload: ExecutionContextDescription, world: DOMWorld);
|
||||
frame(): Frame | null;
|
||||
evaluate<ReturnType>(pageFunction: Function | string, ...args: unknown[]): Promise<ReturnType>;
|
||||
evaluateHandle<HandleType extends JSHandle | ElementHandle = JSHandle>(pageFunction: EvaluateHandleFn, ...args: SerializableOrJSHandle[]): Promise<HandleType>;
|
||||
}
|
||||
Generated
Vendored
+171
@@ -0,0 +1,171 @@
|
||||
"use strict";
|
||||
/* eslint-disable no-new-func */
|
||||
/* eslint-disable no-new */
|
||||
/**
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ExecutionContext = exports.EVALUATION_SCRIPT_URL = void 0;
|
||||
const JSHandle_1 = require("./JSHandle");
|
||||
const util_1 = require("./util");
|
||||
exports.EVALUATION_SCRIPT_URL = 'pptr://__puppeteer_evaluation_script__';
|
||||
const SOURCE_URL_REGEX = /^[\x20\t]*\/\/[@#] sourceURL=\s*(\S*?)\s*$/m;
|
||||
class ExecutionContext {
|
||||
_client;
|
||||
_world;
|
||||
_contextId;
|
||||
_contextName;
|
||||
constructor(client, contextPayload, world) {
|
||||
this._client = client;
|
||||
this._world = world;
|
||||
this._contextId = contextPayload.id;
|
||||
this._contextName = contextPayload.name;
|
||||
}
|
||||
frame() {
|
||||
return this._world ? this._world.frame() : null;
|
||||
}
|
||||
evaluate(pageFunction, ...args) {
|
||||
return this.#evaluate(true, pageFunction, ...args);
|
||||
}
|
||||
evaluateHandle(pageFunction, ...args) {
|
||||
return this.#evaluate(false, pageFunction, ...args);
|
||||
}
|
||||
async #evaluate(returnByValue, pageFunction, ...args) {
|
||||
const suffix = `//# sourceURL=${exports.EVALUATION_SCRIPT_URL}`;
|
||||
if ((0, util_1.isString)(pageFunction)) {
|
||||
const contextId = this._contextId;
|
||||
const expression = pageFunction;
|
||||
const expressionWithSourceUrl = SOURCE_URL_REGEX.test(expression)
|
||||
? expression
|
||||
: expression + '\n' + suffix;
|
||||
const { value: { exceptionDetails: _details, result: _remoteObject }, } = await this._client
|
||||
.send('Runtime.evaluate', {
|
||||
expression: expressionWithSourceUrl,
|
||||
contextId,
|
||||
returnByValue,
|
||||
awaitPromise: true,
|
||||
userGesture: true,
|
||||
})
|
||||
.catch(rewriteError);
|
||||
if (_details) {
|
||||
throw new Error('Evaluation failed: ' + (0, util_1.getExceptionMessage)(_details));
|
||||
}
|
||||
return returnByValue
|
||||
? (0, util_1.valueFromRemoteObject)(_remoteObject)
|
||||
: (0, JSHandle_1._createJSHandle)(this, _remoteObject);
|
||||
}
|
||||
if (typeof pageFunction !== 'function') {
|
||||
throw new Error(`Expected to get |string| or |function| as the first argument, but got "${pageFunction}" instead.`);
|
||||
}
|
||||
let functionText = pageFunction.toString();
|
||||
try {
|
||||
new Function('(' + functionText + ')');
|
||||
}
|
||||
catch (error) {
|
||||
// This means we might have a function shorthand. Try another
|
||||
// time prefixing 'function '.
|
||||
if (functionText.startsWith('async ')) {
|
||||
functionText =
|
||||
'async function ' + functionText.substring('async '.length);
|
||||
}
|
||||
else {
|
||||
functionText = 'function ' + functionText;
|
||||
}
|
||||
try {
|
||||
new Function('(' + functionText + ')');
|
||||
}
|
||||
catch (_error) {
|
||||
// We tried hard to serialize, but there's a weird beast here.
|
||||
throw new Error('Passed function is not well-serializable!');
|
||||
}
|
||||
}
|
||||
let callFunctionOnPromise;
|
||||
try {
|
||||
callFunctionOnPromise = this._client.send('Runtime.callFunctionOn', {
|
||||
functionDeclaration: functionText + '\n' + suffix + '\n',
|
||||
executionContextId: this._contextId,
|
||||
arguments: args.map(convertArgument.bind(this)),
|
||||
returnByValue,
|
||||
awaitPromise: true,
|
||||
userGesture: true,
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof TypeError &&
|
||||
error.message.startsWith('Converting circular structure to JSON')) {
|
||||
error.message += ' Recursive objects are not allowed.';
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
const { value: { exceptionDetails, result: remoteObject }, } = await callFunctionOnPromise.catch(rewriteError);
|
||||
if (exceptionDetails) {
|
||||
throw new Error('Evaluation failed: ' + (0, util_1.getExceptionMessage)(exceptionDetails));
|
||||
}
|
||||
return returnByValue
|
||||
? (0, util_1.valueFromRemoteObject)(remoteObject)
|
||||
: (0, JSHandle_1._createJSHandle)(this, remoteObject);
|
||||
function convertArgument(arg) {
|
||||
if (typeof arg === 'bigint') {
|
||||
// eslint-disable-line valid-typeof
|
||||
return { unserializableValue: `${arg.toString()}n` };
|
||||
}
|
||||
if (Object.is(arg, -0)) {
|
||||
return { unserializableValue: '-0' };
|
||||
}
|
||||
if (Object.is(arg, Infinity)) {
|
||||
return { unserializableValue: 'Infinity' };
|
||||
}
|
||||
if (Object.is(arg, -Infinity)) {
|
||||
return { unserializableValue: '-Infinity' };
|
||||
}
|
||||
if (Object.is(arg, NaN)) {
|
||||
return { unserializableValue: 'NaN' };
|
||||
}
|
||||
const objectHandle = arg && arg instanceof JSHandle_1.JSHandle ? arg : null;
|
||||
if (objectHandle) {
|
||||
if (objectHandle._context !== this) {
|
||||
throw new Error('JSHandles can be evaluated only in the context they were created!');
|
||||
}
|
||||
if (objectHandle._disposed) {
|
||||
throw new Error('JSHandle is disposed!');
|
||||
}
|
||||
if (objectHandle._remoteObject.unserializableValue) {
|
||||
return {
|
||||
unserializableValue: objectHandle._remoteObject.unserializableValue,
|
||||
};
|
||||
}
|
||||
if (!objectHandle._remoteObject.objectId) {
|
||||
return { value: objectHandle._remoteObject.value };
|
||||
}
|
||||
return { objectId: objectHandle._remoteObject.objectId };
|
||||
}
|
||||
return { value: arg };
|
||||
}
|
||||
function rewriteError(error) {
|
||||
if (error.message.includes('Object reference chain is too long')) {
|
||||
return { value: { result: { type: 'undefined' } }, size: 1 };
|
||||
}
|
||||
if (error.message.includes("Object couldn't be returned by value")) {
|
||||
return { value: { result: { type: 'undefined' } }, size: 1 };
|
||||
}
|
||||
if (error.message.endsWith('Cannot find context with specified id') ||
|
||||
error.message.endsWith('Inspected target navigated or closed')) {
|
||||
throw new Error('Execution context was destroyed, most likely because of a navigation.');
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.ExecutionContext = ExecutionContext;
|
||||
Generated
Vendored
+89
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
import type { LogLevel } from '../log-level';
|
||||
import type { Page } from './BrowserPage';
|
||||
import type { CDPSession } from './Connection';
|
||||
import { DOMWorld } from './DOMWorld';
|
||||
import type { EvaluateFn, EvaluateFnReturnType, EvaluateHandleFn, SerializableOrJSHandle, UnwrapPromiseLike } from './EvalTypes';
|
||||
import { EventEmitter } from './EventEmitter';
|
||||
import { ExecutionContext } from './ExecutionContext';
|
||||
import type { HTTPResponse } from './HTTPResponse';
|
||||
import type { JSHandle } from './JSHandle';
|
||||
import type { PuppeteerLifeCycleEvent } from './LifecycleWatcher';
|
||||
import { NetworkManager } from './NetworkManager';
|
||||
import type { Frame as TFrame } from './devtools-types';
|
||||
export declare const FrameManagerEmittedEvents: {
|
||||
FrameNavigated: symbol;
|
||||
FrameDetached: symbol;
|
||||
FrameSwapped: symbol;
|
||||
LifecycleEvent: symbol;
|
||||
FrameNavigatedWithinDocument: symbol;
|
||||
ExecutionContextCreated: symbol;
|
||||
ExecutionContextDestroyed: symbol;
|
||||
};
|
||||
export declare class FrameManager extends EventEmitter {
|
||||
#private;
|
||||
get _client(): CDPSession;
|
||||
constructor(client: CDPSession, page: Page, indent: boolean, logLevel: LogLevel);
|
||||
private setupEventListeners;
|
||||
initialize(client?: CDPSession): Promise<void>;
|
||||
networkManager(): NetworkManager;
|
||||
navigateFrame(frame: Frame, url: string, timeout: number, options?: {
|
||||
referer?: string;
|
||||
timeout?: number;
|
||||
waitUntil?: PuppeteerLifeCycleEvent;
|
||||
}): Promise<HTTPResponse | null>;
|
||||
page(): Page;
|
||||
mainFrame(): Frame;
|
||||
frames(): Frame[];
|
||||
frame(frameId: string): Frame | null;
|
||||
_ensureIsolatedWorld(session: CDPSession, name: string): Promise<void>;
|
||||
executionContextById(contextId: number, session?: CDPSession): ExecutionContext;
|
||||
}
|
||||
export declare class Frame {
|
||||
#private;
|
||||
_frameManager: FrameManager;
|
||||
_id: string;
|
||||
_loaderId: string;
|
||||
_name?: string;
|
||||
_hasStartedLoading: boolean;
|
||||
_lifecycleEvents: Set<string>;
|
||||
_mainWorld: DOMWorld;
|
||||
_secondaryWorld: DOMWorld;
|
||||
_childFrames: Set<Frame>;
|
||||
constructor(frameManager: FrameManager, parentFrame: Frame | null, frameId: string, client: CDPSession);
|
||||
_updateClient(client: CDPSession): void;
|
||||
isOOPFrame(): boolean;
|
||||
goto(url: string, timeout: number, options?: {
|
||||
referer?: string;
|
||||
waitUntil?: PuppeteerLifeCycleEvent;
|
||||
}): Promise<HTTPResponse | null>;
|
||||
_client(): CDPSession;
|
||||
/**
|
||||
* @returns a promise that resolves to the frame's default execution context.
|
||||
*/
|
||||
executionContext(): Promise<ExecutionContext>;
|
||||
evaluateHandle<HandlerType extends JSHandle = JSHandle>(pageFunction: EvaluateHandleFn, ...args: SerializableOrJSHandle[]): Promise<HandlerType>;
|
||||
evaluate<T extends EvaluateFn>(pageFunction: T, ...args: SerializableOrJSHandle[]): Promise<UnwrapPromiseLike<EvaluateFnReturnType<T>>>;
|
||||
url(): string;
|
||||
childFrames(): Frame[];
|
||||
_navigated(framePayload: TFrame): void;
|
||||
_navigatedWithinDocument(url: string): void;
|
||||
_onLifecycleEvent(loaderId: string, name: string): void;
|
||||
_onLoadingStopped(): void;
|
||||
_onLoadingStarted(): void;
|
||||
_detach(): void;
|
||||
}
|
||||
Generated
Vendored
+492
@@ -0,0 +1,492 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Frame = exports.FrameManager = exports.FrameManagerEmittedEvents = void 0;
|
||||
const Connection_1 = require("./Connection");
|
||||
const DOMWorld_1 = require("./DOMWorld");
|
||||
const EventEmitter_1 = require("./EventEmitter");
|
||||
const ExecutionContext_1 = require("./ExecutionContext");
|
||||
const LifecycleWatcher_1 = require("./LifecycleWatcher");
|
||||
const NetworkManager_1 = require("./NetworkManager");
|
||||
const assert_1 = require("./assert");
|
||||
const flaky_errors_1 = require("./flaky-errors");
|
||||
const util_1 = require("./util");
|
||||
const UTILITY_WORLD_NAME = '__puppeteer_utility_world__';
|
||||
exports.FrameManagerEmittedEvents = {
|
||||
FrameNavigated: Symbol('FrameManager.FrameNavigated'),
|
||||
FrameDetached: Symbol('FrameManager.FrameDetached'),
|
||||
FrameSwapped: Symbol('FrameManager.FrameSwapped'),
|
||||
LifecycleEvent: Symbol('FrameManager.LifecycleEvent'),
|
||||
FrameNavigatedWithinDocument: Symbol('FrameManager.FrameNavigatedWithinDocument'),
|
||||
ExecutionContextCreated: Symbol('FrameManager.ExecutionContextCreated'),
|
||||
ExecutionContextDestroyed: Symbol('FrameManager.ExecutionContextDestroyed'),
|
||||
};
|
||||
class FrameManager extends EventEmitter_1.EventEmitter {
|
||||
#page;
|
||||
#networkManager;
|
||||
#frames = new Map();
|
||||
#contextIdToContext = new Map();
|
||||
#isolatedWorlds = new Set();
|
||||
#mainFrame;
|
||||
#client;
|
||||
get _client() {
|
||||
return this.#client;
|
||||
}
|
||||
constructor(client, page, indent, logLevel) {
|
||||
super();
|
||||
this.#client = client;
|
||||
this.#page = page;
|
||||
this.#networkManager = new NetworkManager_1.NetworkManager(client, this, indent, logLevel);
|
||||
this.setupEventListeners(this.#client);
|
||||
}
|
||||
setupEventListeners(session) {
|
||||
session.on('Page.frameAttached', (event) => {
|
||||
this.#onFrameAttached(session, event.frameId, event.parentFrameId);
|
||||
});
|
||||
session.on('Page.frameNavigated', (event) => {
|
||||
this.#onFrameNavigated(event.frame);
|
||||
});
|
||||
session.on('Page.navigatedWithinDocument', (event) => {
|
||||
this.#onFrameNavigatedWithinDocument(event.frameId, event.url);
|
||||
});
|
||||
session.on('Page.frameDetached', (event) => {
|
||||
this.#onFrameDetached(event.frameId, event.reason);
|
||||
});
|
||||
session.on('Page.frameStartedLoading', (event) => {
|
||||
this.#onFrameStartedLoading(event.frameId);
|
||||
});
|
||||
session.on('Page.frameStoppedLoading', (event) => {
|
||||
this.#onFrameStoppedLoading(event.frameId);
|
||||
});
|
||||
session.on('Runtime.executionContextCreated', (event) => {
|
||||
this.#onExecutionContextCreated(event.context, session);
|
||||
});
|
||||
session.on('Runtime.executionContextDestroyed', (event) => {
|
||||
this.#onExecutionContextDestroyed(event.executionContextId, session);
|
||||
});
|
||||
session.on('Runtime.executionContextsCleared', () => {
|
||||
this.#onExecutionContextsCleared(session);
|
||||
});
|
||||
session.on('Page.lifecycleEvent', (event) => {
|
||||
this.#onLifecycleEvent(event);
|
||||
});
|
||||
session.on('Target.attachedToTarget', (event) => {
|
||||
this.#onAttachedToTarget(event);
|
||||
});
|
||||
session.on('Target.detachedFromTarget', (event) => {
|
||||
this.#onDetachedFromTarget(event);
|
||||
});
|
||||
}
|
||||
async initialize(client = this.#client) {
|
||||
try {
|
||||
const result = await Promise.all([
|
||||
client.send('Page.enable'),
|
||||
client.send('Page.getFrameTree'),
|
||||
client === this.#client
|
||||
? Promise.resolve()
|
||||
: client.send('Target.setAutoAttach', {
|
||||
autoAttach: true,
|
||||
waitForDebuggerOnStart: false,
|
||||
flatten: true,
|
||||
}),
|
||||
]);
|
||||
const { value: { frameTree }, } = result[1];
|
||||
this.#handleFrameTree(client, frameTree);
|
||||
await Promise.all([
|
||||
client.send('Page.setLifecycleEventsEnabled', { enabled: true }),
|
||||
client.send('Runtime.enable').then(() => {
|
||||
return this._ensureIsolatedWorld(client, UTILITY_WORLD_NAME);
|
||||
}),
|
||||
client === this.#client
|
||||
? this.#networkManager.initialize()
|
||||
: Promise.resolve(),
|
||||
]);
|
||||
}
|
||||
catch (error) {
|
||||
// The target might have been closed before the initialization finished.
|
||||
if ((0, util_1.isErrorLike)(error) && (0, flaky_errors_1.isTargetClosedErr)(error)) {
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
networkManager() {
|
||||
return this.#networkManager;
|
||||
}
|
||||
async navigateFrame(frame, url, timeout, options = {}) {
|
||||
const { referer = undefined, waitUntil = 'load' } = options;
|
||||
const watcher = new LifecycleWatcher_1.LifecycleWatcher(this, frame, waitUntil, timeout);
|
||||
let error = await Promise.race([
|
||||
navigate(this.#client, url, referer, frame._id),
|
||||
watcher.timeoutOrTerminationPromise(),
|
||||
]);
|
||||
if (!error) {
|
||||
error = await Promise.race([
|
||||
watcher.timeoutOrTerminationPromise(),
|
||||
watcher.newDocumentNavigationPromise(),
|
||||
watcher.sameDocumentNavigationPromise(),
|
||||
]);
|
||||
}
|
||||
watcher.dispose();
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
return watcher.navigationResponse();
|
||||
async function navigate(client, _url, referrer, frameId) {
|
||||
try {
|
||||
const { value: response } = await client.send('Page.navigate', {
|
||||
url: _url,
|
||||
referrer,
|
||||
frameId,
|
||||
});
|
||||
return response.errorText
|
||||
? new Error(`${response.errorText} at ${_url}`)
|
||||
: null;
|
||||
}
|
||||
catch (_error) {
|
||||
if ((0, util_1.isErrorLike)(_error)) {
|
||||
return _error;
|
||||
}
|
||||
throw _error;
|
||||
}
|
||||
}
|
||||
}
|
||||
async #onAttachedToTarget(event) {
|
||||
if (event.targetInfo.type !== 'iframe') {
|
||||
return;
|
||||
}
|
||||
const frame = this.#frames.get(event.targetInfo.targetId);
|
||||
const connection = Connection_1.Connection.fromSession(this.#client);
|
||||
(0, assert_1.assert)(connection);
|
||||
const session = connection.session(event.sessionId);
|
||||
(0, assert_1.assert)(session);
|
||||
if (frame) {
|
||||
frame._updateClient(session);
|
||||
}
|
||||
this.setupEventListeners(session);
|
||||
await this.initialize(session);
|
||||
}
|
||||
#onDetachedFromTarget(event) {
|
||||
if (!event.targetId) {
|
||||
return;
|
||||
}
|
||||
const frame = this.#frames.get(event.targetId);
|
||||
if (frame === null || frame === void 0 ? void 0 : frame.isOOPFrame()) {
|
||||
// When an OOP iframe is removed from the page, it
|
||||
// will only get a Target.detachedFromTarget event.
|
||||
this.#removeFramesRecursively(frame);
|
||||
}
|
||||
}
|
||||
#onLifecycleEvent(event) {
|
||||
const frame = this.#frames.get(event.frameId);
|
||||
if (!frame) {
|
||||
return;
|
||||
}
|
||||
frame._onLifecycleEvent(event.loaderId, event.name);
|
||||
this.emit(exports.FrameManagerEmittedEvents.LifecycleEvent, frame);
|
||||
}
|
||||
#onFrameStartedLoading(frameId) {
|
||||
const frame = this.#frames.get(frameId);
|
||||
if (!frame) {
|
||||
return;
|
||||
}
|
||||
frame._onLoadingStarted();
|
||||
}
|
||||
#onFrameStoppedLoading(frameId) {
|
||||
const frame = this.#frames.get(frameId);
|
||||
if (!frame) {
|
||||
return;
|
||||
}
|
||||
frame._onLoadingStopped();
|
||||
this.emit(exports.FrameManagerEmittedEvents.LifecycleEvent, frame);
|
||||
}
|
||||
#handleFrameTree(session, frameTree) {
|
||||
if (frameTree.frame.parentId) {
|
||||
this.#onFrameAttached(session, frameTree.frame.id, frameTree.frame.parentId);
|
||||
}
|
||||
this.#onFrameNavigated(frameTree.frame);
|
||||
if (!frameTree.childFrames) {
|
||||
return;
|
||||
}
|
||||
for (const child of frameTree.childFrames) {
|
||||
this.#handleFrameTree(session, child);
|
||||
}
|
||||
}
|
||||
page() {
|
||||
return this.#page;
|
||||
}
|
||||
mainFrame() {
|
||||
(0, assert_1.assert)(this.#mainFrame, 'Requesting main frame too early!');
|
||||
return this.#mainFrame;
|
||||
}
|
||||
frames() {
|
||||
return Array.from(this.#frames.values());
|
||||
}
|
||||
frame(frameId) {
|
||||
return this.#frames.get(frameId) || null;
|
||||
}
|
||||
#onFrameAttached(session, frameId, parentFrameId) {
|
||||
if (this.#frames.has(frameId)) {
|
||||
const _frame = this.#frames.get(frameId);
|
||||
if (session && _frame.isOOPFrame()) {
|
||||
// If an OOP iframes becomes a normal iframe again
|
||||
// it is first attached to the parent page before
|
||||
// the target is removed.
|
||||
_frame._updateClient(session);
|
||||
}
|
||||
return;
|
||||
}
|
||||
(0, assert_1.assert)(parentFrameId);
|
||||
const parentFrame = this.#frames.get(parentFrameId);
|
||||
(0, assert_1.assert)(parentFrame);
|
||||
const frame = new Frame(this, parentFrame, frameId, session);
|
||||
this.#frames.set(frame._id, frame);
|
||||
}
|
||||
#onFrameNavigated(framePayload) {
|
||||
const isMainFrame = !framePayload.parentId;
|
||||
let frame = isMainFrame
|
||||
? this.#mainFrame
|
||||
: this.#frames.get(framePayload.id);
|
||||
(0, assert_1.assert)(isMainFrame || frame, 'We either navigate top level or have old version of the navigated frame');
|
||||
// Detach all child frames first.
|
||||
if (frame) {
|
||||
for (const child of frame.childFrames()) {
|
||||
this.#removeFramesRecursively(child);
|
||||
}
|
||||
}
|
||||
// Update or create main frame.
|
||||
if (isMainFrame) {
|
||||
if (frame) {
|
||||
// Update frame id to retain frame identity on cross-process navigation.
|
||||
this.#frames.delete(frame._id);
|
||||
frame._id = framePayload.id;
|
||||
}
|
||||
else {
|
||||
// Initial main frame navigation.
|
||||
frame = new Frame(this, null, framePayload.id, this.#client);
|
||||
}
|
||||
this.#frames.set(framePayload.id, frame);
|
||||
this.#mainFrame = frame;
|
||||
}
|
||||
// Update frame payload.
|
||||
(0, assert_1.assert)(frame);
|
||||
frame._navigated(framePayload);
|
||||
this.emit(exports.FrameManagerEmittedEvents.FrameNavigated, frame);
|
||||
}
|
||||
async _ensureIsolatedWorld(session, name) {
|
||||
const key = `${session.id()}:${name}`;
|
||||
if (this.#isolatedWorlds.has(key)) {
|
||||
return;
|
||||
}
|
||||
this.#isolatedWorlds.add(key);
|
||||
await session.send('Page.addScriptToEvaluateOnNewDocument', {
|
||||
source: `//# sourceURL=${ExecutionContext_1.EVALUATION_SCRIPT_URL}`,
|
||||
worldName: name,
|
||||
});
|
||||
// Frames might be removed before we send this.
|
||||
await Promise.all(this.frames()
|
||||
.filter((frame) => {
|
||||
return frame._client() === session;
|
||||
})
|
||||
.map((frame) => {
|
||||
return session
|
||||
.send('Page.createIsolatedWorld', {
|
||||
frameId: frame._id,
|
||||
worldName: name,
|
||||
grantUniveralAccess: true,
|
||||
})
|
||||
.catch(() => undefined);
|
||||
}));
|
||||
}
|
||||
#onFrameNavigatedWithinDocument(frameId, url) {
|
||||
const frame = this.#frames.get(frameId);
|
||||
if (!frame) {
|
||||
return;
|
||||
}
|
||||
frame._navigatedWithinDocument(url);
|
||||
this.emit(exports.FrameManagerEmittedEvents.FrameNavigatedWithinDocument, frame);
|
||||
this.emit(exports.FrameManagerEmittedEvents.FrameNavigated, frame);
|
||||
}
|
||||
#onFrameDetached(frameId, reason) {
|
||||
const frame = this.#frames.get(frameId);
|
||||
if (reason === 'remove') {
|
||||
// Only remove the frame if the reason for the detached event is
|
||||
// an actual removement of the frame.
|
||||
// For frames that become OOP iframes, the reason would be 'swap'.
|
||||
if (frame) {
|
||||
this.#removeFramesRecursively(frame);
|
||||
}
|
||||
}
|
||||
else if (reason === 'swap') {
|
||||
this.emit(exports.FrameManagerEmittedEvents.FrameSwapped, frame);
|
||||
}
|
||||
}
|
||||
#onExecutionContextCreated(contextPayload, session) {
|
||||
const auxData = contextPayload.auxData;
|
||||
const frameId = auxData === null || auxData === void 0 ? void 0 : auxData.frameId;
|
||||
const frame = typeof frameId === 'string' ? this.#frames.get(frameId) : undefined;
|
||||
let world;
|
||||
if (frame) {
|
||||
// Only care about execution contexts created for the current session.
|
||||
if (frame._client() !== session) {
|
||||
return;
|
||||
}
|
||||
if (contextPayload.auxData && Boolean(contextPayload.auxData.isDefault)) {
|
||||
world = frame._mainWorld;
|
||||
}
|
||||
else if (contextPayload.name === UTILITY_WORLD_NAME &&
|
||||
!frame._secondaryWorld._hasContext()) {
|
||||
// In case of multiple sessions to the same target, there's a race between
|
||||
// connections so we might end up creating multiple isolated worlds.
|
||||
// We can use either.
|
||||
world = frame._secondaryWorld;
|
||||
}
|
||||
}
|
||||
const context = new ExecutionContext_1.ExecutionContext((frame === null || frame === void 0 ? void 0 : frame._client()) || this.#client, contextPayload, world);
|
||||
if (world) {
|
||||
world._setContext(context);
|
||||
}
|
||||
const key = `${session.id()}:${contextPayload.id}`;
|
||||
this.#contextIdToContext.set(key, context);
|
||||
}
|
||||
#onExecutionContextDestroyed(executionContextId, session) {
|
||||
const key = `${session.id()}:${executionContextId}`;
|
||||
const context = this.#contextIdToContext.get(key);
|
||||
if (!context) {
|
||||
return;
|
||||
}
|
||||
this.#contextIdToContext.delete(key);
|
||||
if (context._world) {
|
||||
context._world._setContext(null);
|
||||
}
|
||||
}
|
||||
#onExecutionContextsCleared(session) {
|
||||
for (const [key, context] of this.#contextIdToContext.entries()) {
|
||||
// Make sure to only clear execution contexts that belong
|
||||
// to the current session.
|
||||
if (context._client !== session) {
|
||||
continue;
|
||||
}
|
||||
if (context._world) {
|
||||
context._world._setContext(null);
|
||||
}
|
||||
this.#contextIdToContext.delete(key);
|
||||
}
|
||||
}
|
||||
executionContextById(contextId, session = this.#client) {
|
||||
const key = `${session.id()}:${contextId}`;
|
||||
const context = this.#contextIdToContext.get(key);
|
||||
(0, assert_1.assert)(context, 'INTERNAL ERROR: missing context with id = ' + contextId);
|
||||
return context;
|
||||
}
|
||||
#removeFramesRecursively(frame) {
|
||||
for (const child of frame.childFrames()) {
|
||||
this.#removeFramesRecursively(child);
|
||||
}
|
||||
frame._detach();
|
||||
this.#frames.delete(frame._id);
|
||||
this.emit(exports.FrameManagerEmittedEvents.FrameDetached, frame);
|
||||
}
|
||||
}
|
||||
exports.FrameManager = FrameManager;
|
||||
class Frame {
|
||||
#parentFrame;
|
||||
#url = '';
|
||||
#client;
|
||||
_frameManager;
|
||||
_id;
|
||||
_loaderId = '';
|
||||
_name;
|
||||
_hasStartedLoading = false;
|
||||
_lifecycleEvents = new Set();
|
||||
_mainWorld;
|
||||
_secondaryWorld;
|
||||
_childFrames;
|
||||
constructor(frameManager, parentFrame, frameId, client) {
|
||||
this._frameManager = frameManager;
|
||||
this.#parentFrame = parentFrame !== null && parentFrame !== void 0 ? parentFrame : null;
|
||||
this.#url = '';
|
||||
this._id = frameId;
|
||||
this._loaderId = '';
|
||||
this._childFrames = new Set();
|
||||
if (this.#parentFrame) {
|
||||
this.#parentFrame._childFrames.add(this);
|
||||
}
|
||||
this._updateClient(client);
|
||||
}
|
||||
_updateClient(client) {
|
||||
this.#client = client;
|
||||
this._mainWorld = new DOMWorld_1.DOMWorld(this);
|
||||
this._secondaryWorld = new DOMWorld_1.DOMWorld(this);
|
||||
}
|
||||
isOOPFrame() {
|
||||
return this.#client !== this._frameManager._client;
|
||||
}
|
||||
goto(url, timeout, options = {}) {
|
||||
return this._frameManager.navigateFrame(this, url, timeout, options);
|
||||
}
|
||||
_client() {
|
||||
return this.#client;
|
||||
}
|
||||
/**
|
||||
* @returns a promise that resolves to the frame's default execution context.
|
||||
*/
|
||||
executionContext() {
|
||||
return this._mainWorld.executionContext();
|
||||
}
|
||||
evaluateHandle(pageFunction, ...args) {
|
||||
return this._mainWorld.evaluateHandle(pageFunction, ...args);
|
||||
}
|
||||
evaluate(pageFunction, ...args) {
|
||||
return this._mainWorld.evaluate(pageFunction, ...args);
|
||||
}
|
||||
url() {
|
||||
return this.#url;
|
||||
}
|
||||
childFrames() {
|
||||
return Array.from(this._childFrames);
|
||||
}
|
||||
_navigated(framePayload) {
|
||||
this._name = framePayload.name;
|
||||
this.#url = `${framePayload.url}${framePayload.urlFragment || ''}`;
|
||||
}
|
||||
_navigatedWithinDocument(url) {
|
||||
this.#url = url;
|
||||
}
|
||||
_onLifecycleEvent(loaderId, name) {
|
||||
if (name === 'init') {
|
||||
this._loaderId = loaderId;
|
||||
this._lifecycleEvents.clear();
|
||||
}
|
||||
this._lifecycleEvents.add(name);
|
||||
}
|
||||
_onLoadingStopped() {
|
||||
this._lifecycleEvents.add('load');
|
||||
}
|
||||
_onLoadingStarted() {
|
||||
this._hasStartedLoading = true;
|
||||
}
|
||||
_detach() {
|
||||
this._mainWorld._detach();
|
||||
this._secondaryWorld._detach();
|
||||
if (this.#parentFrame) {
|
||||
this.#parentFrame._childFrames.delete(this);
|
||||
}
|
||||
this.#parentFrame = null;
|
||||
}
|
||||
}
|
||||
exports.Frame = Frame;
|
||||
Generated
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
import type { RequestWillBeSentEvent } from './devtools-types';
|
||||
import type { Frame } from './FrameManager';
|
||||
import type { HTTPResponse } from './HTTPResponse';
|
||||
export declare class HTTPRequest {
|
||||
#private;
|
||||
_requestId: string;
|
||||
_response: HTTPResponse | null;
|
||||
_url: string | null;
|
||||
_fromMemoryCache: boolean;
|
||||
constructor(frame: Frame | null, event: RequestWillBeSentEvent);
|
||||
response(): HTTPResponse | null;
|
||||
frame(): Frame | null;
|
||||
isNavigationRequest(): boolean;
|
||||
}
|
||||
Generated
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.HTTPRequest = void 0;
|
||||
class HTTPRequest {
|
||||
_requestId;
|
||||
_response = null;
|
||||
_url = null;
|
||||
_fromMemoryCache = false;
|
||||
#isNavigationRequest;
|
||||
#frame;
|
||||
constructor(frame, event) {
|
||||
this._requestId = event.requestId;
|
||||
this.#isNavigationRequest =
|
||||
event.requestId === event.loaderId && event.type === 'Document';
|
||||
this.#frame = frame;
|
||||
this._url = event.request.url;
|
||||
}
|
||||
response() {
|
||||
return this._response;
|
||||
}
|
||||
frame() {
|
||||
return this.#frame;
|
||||
}
|
||||
isNavigationRequest() {
|
||||
return this.#isNavigationRequest;
|
||||
}
|
||||
}
|
||||
exports.HTTPRequest = HTTPRequest;
|
||||
Generated
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
import type { Response, ResponseReceivedExtraInfoEvent } from './devtools-types';
|
||||
export declare class HTTPResponse {
|
||||
#private;
|
||||
constructor(responsePayload: Response, extraInfo: ResponseReceivedExtraInfoEvent | null);
|
||||
status(): number;
|
||||
}
|
||||
Generated
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.HTTPResponse = void 0;
|
||||
class HTTPResponse {
|
||||
#status;
|
||||
constructor(responsePayload, extraInfo) {
|
||||
this.#status = extraInfo ? extraInfo.statusCode : responsePayload.status;
|
||||
}
|
||||
status() {
|
||||
return this.#status;
|
||||
}
|
||||
}
|
||||
exports.HTTPResponse = HTTPResponse;
|
||||
Generated
Vendored
+35
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
import type { CDPSession } from './Connection';
|
||||
import type { DevtoolsRemoteObject } from './devtools-types';
|
||||
import type { EvaluateHandleFn, SerializableOrJSHandle } from './EvalTypes';
|
||||
import type { ExecutionContext } from './ExecutionContext';
|
||||
export declare function _createJSHandle(context: ExecutionContext, remoteObject: DevtoolsRemoteObject): JSHandle;
|
||||
export declare class JSHandle {
|
||||
#private;
|
||||
get _disposed(): boolean;
|
||||
get _remoteObject(): DevtoolsRemoteObject;
|
||||
get _context(): ExecutionContext;
|
||||
constructor(context: ExecutionContext, client: CDPSession, remoteObject: DevtoolsRemoteObject);
|
||||
executionContext(): ExecutionContext;
|
||||
evaluateHandle<HandleType extends JSHandle = JSHandle>(pageFunction: EvaluateHandleFn, ...args: SerializableOrJSHandle[]): Promise<HandleType>;
|
||||
asElement(): ElementHandle | null;
|
||||
dispose(): Promise<void>;
|
||||
toString(): string;
|
||||
}
|
||||
export declare class ElementHandle<ElementType extends Element = Element> extends JSHandle {
|
||||
asElement(): ElementHandle<ElementType> | null;
|
||||
}
|
||||
Generated
Vendored
+77
@@ -0,0 +1,77 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ElementHandle = exports.JSHandle = void 0;
|
||||
exports._createJSHandle = _createJSHandle;
|
||||
const util_1 = require("./util");
|
||||
function _createJSHandle(context, remoteObject) {
|
||||
const frame = context.frame();
|
||||
if (remoteObject.subtype === 'node' && frame) {
|
||||
return new ElementHandle(context, context._client, remoteObject);
|
||||
}
|
||||
return new JSHandle(context, context._client, remoteObject);
|
||||
}
|
||||
class JSHandle {
|
||||
#client;
|
||||
#disposed = false;
|
||||
#context;
|
||||
#remoteObject;
|
||||
get _disposed() {
|
||||
return this.#disposed;
|
||||
}
|
||||
get _remoteObject() {
|
||||
return this.#remoteObject;
|
||||
}
|
||||
get _context() {
|
||||
return this.#context;
|
||||
}
|
||||
constructor(context, client, remoteObject) {
|
||||
this.#context = context;
|
||||
this.#client = client;
|
||||
this.#remoteObject = remoteObject;
|
||||
}
|
||||
executionContext() {
|
||||
return this.#context;
|
||||
}
|
||||
evaluateHandle(pageFunction, ...args) {
|
||||
return this.executionContext().evaluateHandle(pageFunction, this, ...args);
|
||||
}
|
||||
asElement() {
|
||||
return null;
|
||||
}
|
||||
async dispose() {
|
||||
if (this.#disposed) {
|
||||
return;
|
||||
}
|
||||
this.#disposed = true;
|
||||
await (0, util_1.releaseObject)(this.#client, this.#remoteObject);
|
||||
}
|
||||
toString() {
|
||||
if (this.#remoteObject.objectId) {
|
||||
const type = this.#remoteObject.subtype || this.#remoteObject.type;
|
||||
return 'JSHandle@' + type;
|
||||
}
|
||||
return (0, util_1.valueFromRemoteObject)(this.#remoteObject);
|
||||
}
|
||||
}
|
||||
exports.JSHandle = JSHandle;
|
||||
class ElementHandle extends JSHandle {
|
||||
asElement() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
exports.ElementHandle = ElementHandle;
|
||||
Generated
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
import type { LogLevel } from '../log-level';
|
||||
import type { Viewport } from './PuppeteerViewport';
|
||||
export interface LaunchOptions {
|
||||
args: string[];
|
||||
executablePath: string;
|
||||
logLevel: LogLevel;
|
||||
indent: boolean;
|
||||
defaultViewport: Viewport;
|
||||
userDataDir: string;
|
||||
timeout: number;
|
||||
}
|
||||
Generated
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
Generated
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
import { HeadlessBrowser } from './Browser';
|
||||
import type { LaunchOptions } from './LaunchOptions';
|
||||
export declare const launchChrome: ({ args, executablePath, defaultViewport, indent, logLevel, userDataDir, timeout, }: LaunchOptions) => Promise<HeadlessBrowser>;
|
||||
Generated
Vendored
+41
@@ -0,0 +1,41 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.launchChrome = void 0;
|
||||
const Browser_1 = require("./Browser");
|
||||
const launchChrome = async ({ args, executablePath, defaultViewport, indent, logLevel, userDataDir, timeout, }) => {
|
||||
const browser = await Browser_1.HeadlessBrowser.create({
|
||||
defaultViewport,
|
||||
args,
|
||||
executablePath,
|
||||
timeout,
|
||||
userDataDir,
|
||||
logLevel,
|
||||
indent,
|
||||
});
|
||||
try {
|
||||
await browser.waitForTarget((t) => {
|
||||
return t.type() === 'page';
|
||||
}, { timeout });
|
||||
}
|
||||
catch (error) {
|
||||
await browser.close({ silent: false });
|
||||
throw error;
|
||||
}
|
||||
return browser;
|
||||
};
|
||||
exports.launchChrome = launchChrome;
|
||||
Generated
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
import { TimeoutError } from './Errors';
|
||||
import type { Frame, FrameManager } from './FrameManager';
|
||||
import type { HTTPResponse } from './HTTPResponse';
|
||||
export type PuppeteerLifeCycleEvent = 'load';
|
||||
export declare class LifecycleWatcher {
|
||||
#private;
|
||||
constructor(frameManager: FrameManager, frame: Frame, waitUntil: PuppeteerLifeCycleEvent, timeout: number);
|
||||
navigationResponse(): HTTPResponse | null;
|
||||
sameDocumentNavigationPromise(): Promise<Error | undefined>;
|
||||
newDocumentNavigationPromise(): Promise<Error | undefined>;
|
||||
lifecyclePromise(): Promise<void>;
|
||||
timeoutOrTerminationPromise(): Promise<Error | TimeoutError | undefined>;
|
||||
dispose(): void;
|
||||
}
|
||||
Generated
Vendored
+174
@@ -0,0 +1,174 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LifecycleWatcher = void 0;
|
||||
const assert_1 = require("./assert");
|
||||
const Connection_1 = require("./Connection");
|
||||
const Errors_1 = require("./Errors");
|
||||
const FrameManager_1 = require("./FrameManager");
|
||||
const NetworkManager_1 = require("./NetworkManager");
|
||||
const util_1 = require("./util");
|
||||
const puppeteerToProtocolLifecycle = new Map([['load', 'load']]);
|
||||
const noop = () => undefined;
|
||||
class LifecycleWatcher {
|
||||
#expectedLifecycle;
|
||||
#frameManager;
|
||||
#frame;
|
||||
#timeout;
|
||||
#navigationRequest = null;
|
||||
#eventListeners;
|
||||
#sameDocumentNavigationCompleteCallback = noop;
|
||||
#sameDocumentNavigationPromise = new Promise((fulfill) => {
|
||||
this.#sameDocumentNavigationCompleteCallback = fulfill;
|
||||
});
|
||||
#lifecycleCallback = noop;
|
||||
#lifecyclePromise = new Promise((fulfill) => {
|
||||
this.#lifecycleCallback = fulfill;
|
||||
});
|
||||
#newDocumentNavigationCompleteCallback = noop;
|
||||
#newDocumentNavigationPromise = new Promise((fulfill) => {
|
||||
this.#newDocumentNavigationCompleteCallback = fulfill;
|
||||
});
|
||||
#terminationCallback = noop;
|
||||
#terminationPromise = new Promise((fulfill) => {
|
||||
this.#terminationCallback = fulfill;
|
||||
});
|
||||
#timeoutPromise;
|
||||
#maximumTimer;
|
||||
#hasSameDocumentNavigation;
|
||||
#newDocumentNavigation;
|
||||
#swapped;
|
||||
constructor(frameManager, frame, waitUntil, timeout) {
|
||||
const protocolEvent = puppeteerToProtocolLifecycle.get(waitUntil);
|
||||
(0, assert_1.assert)(protocolEvent, 'Unknown value for options.waitUntil: ' + waitUntil);
|
||||
this.#expectedLifecycle = [waitUntil];
|
||||
this.#frameManager = frameManager;
|
||||
this.#frame = frame;
|
||||
this.#timeout = timeout;
|
||||
this.#eventListeners = [
|
||||
(0, util_1.addEventListener)(frameManager._client, Connection_1.CDPSessionEmittedEvents.Disconnected, this.#terminate.bind(this, new Error('Navigation failed because browser has disconnected!'))),
|
||||
(0, util_1.addEventListener)(this.#frameManager, FrameManager_1.FrameManagerEmittedEvents.LifecycleEvent, this.#checkLifecycleComplete.bind(this)),
|
||||
(0, util_1.addEventListener)(this.#frameManager, FrameManager_1.FrameManagerEmittedEvents.FrameNavigatedWithinDocument, this.#navigatedWithinDocument.bind(this)),
|
||||
(0, util_1.addEventListener)(this.#frameManager, FrameManager_1.FrameManagerEmittedEvents.FrameNavigated, this.#navigated.bind(this)),
|
||||
(0, util_1.addEventListener)(this.#frameManager, FrameManager_1.FrameManagerEmittedEvents.FrameSwapped, this.#frameSwapped.bind(this)),
|
||||
(0, util_1.addEventListener)(this.#frameManager, FrameManager_1.FrameManagerEmittedEvents.FrameDetached, this.#onFrameDetached.bind(this)),
|
||||
(0, util_1.addEventListener)(this.#frameManager.networkManager(), NetworkManager_1.NetworkManagerEmittedEvents.Request, this.#onRequest.bind(this)),
|
||||
];
|
||||
this.#timeoutPromise = this.#createTimeoutPromise();
|
||||
this.#checkLifecycleComplete();
|
||||
}
|
||||
#onRequest(request) {
|
||||
if (request.frame() !== this.#frame || !request.isNavigationRequest()) {
|
||||
return;
|
||||
}
|
||||
this.#navigationRequest = request;
|
||||
}
|
||||
#onFrameDetached(frame) {
|
||||
if (this.#frame === frame) {
|
||||
this.#terminationCallback.call(null, new Error('Navigating frame was detached'));
|
||||
return;
|
||||
}
|
||||
this.#checkLifecycleComplete();
|
||||
}
|
||||
navigationResponse() {
|
||||
if (!this.#navigationRequest) {
|
||||
return null;
|
||||
}
|
||||
const res = this.#navigationRequest.response();
|
||||
return res;
|
||||
}
|
||||
#terminate(error) {
|
||||
this.#terminationCallback.call(null, error);
|
||||
}
|
||||
sameDocumentNavigationPromise() {
|
||||
return this.#sameDocumentNavigationPromise;
|
||||
}
|
||||
newDocumentNavigationPromise() {
|
||||
return this.#newDocumentNavigationPromise;
|
||||
}
|
||||
lifecyclePromise() {
|
||||
return this.#lifecyclePromise;
|
||||
}
|
||||
timeoutOrTerminationPromise() {
|
||||
return Promise.race([this.#timeoutPromise, this.#terminationPromise]);
|
||||
}
|
||||
async #createTimeoutPromise() {
|
||||
if (!this.#timeout) {
|
||||
return new Promise(noop);
|
||||
}
|
||||
const errorMessage = 'Navigation timeout of ' + this.#timeout + ' ms exceeded';
|
||||
await new Promise((fulfill) => {
|
||||
this.#maximumTimer = setTimeout(fulfill, this.#timeout);
|
||||
});
|
||||
return new Errors_1.TimeoutError(errorMessage);
|
||||
}
|
||||
#navigatedWithinDocument(frame) {
|
||||
if (frame !== this.#frame) {
|
||||
return;
|
||||
}
|
||||
this.#hasSameDocumentNavigation = true;
|
||||
this.#checkLifecycleComplete();
|
||||
}
|
||||
#navigated(frame) {
|
||||
if (frame !== this.#frame) {
|
||||
return;
|
||||
}
|
||||
this.#newDocumentNavigation = true;
|
||||
this.#checkLifecycleComplete();
|
||||
}
|
||||
#frameSwapped(frame) {
|
||||
if (frame !== this.#frame) {
|
||||
return;
|
||||
}
|
||||
this.#swapped = true;
|
||||
this.#checkLifecycleComplete();
|
||||
}
|
||||
#checkLifecycleComplete() {
|
||||
// We expect navigation to commit.
|
||||
if (!checkLifecycle(this.#frame, this.#expectedLifecycle)) {
|
||||
return;
|
||||
}
|
||||
this.#lifecycleCallback();
|
||||
if (this.#hasSameDocumentNavigation) {
|
||||
this.#sameDocumentNavigationCompleteCallback();
|
||||
}
|
||||
if (this.#swapped || this.#newDocumentNavigation) {
|
||||
this.#newDocumentNavigationCompleteCallback();
|
||||
}
|
||||
function checkLifecycle(frame, expectedLifecycle) {
|
||||
for (const event of expectedLifecycle) {
|
||||
if (!frame._lifecycleEvents.has(event)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (const child of frame.childFrames()) {
|
||||
if (child._hasStartedLoading &&
|
||||
!checkLifecycle(child, expectedLifecycle)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
dispose() {
|
||||
(0, util_1.removeEventListeners)(this.#eventListeners);
|
||||
if (this.#maximumTimer !== undefined) {
|
||||
clearTimeout(this.#maximumTimer);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.LifecycleWatcher = LifecycleWatcher;
|
||||
Generated
Vendored
+34
@@ -0,0 +1,34 @@
|
||||
import type { LoadingFailedEvent, LoadingFinishedEvent, RequestPausedEvent, RequestWillBeSentEvent, ResponseReceivedEvent, ResponseReceivedExtraInfoEvent } from './devtools-types';
|
||||
import type { HTTPRequest } from './HTTPRequest';
|
||||
type QueuedEventGroup = {
|
||||
responseReceivedEvent: ResponseReceivedEvent;
|
||||
loadingFinishedEvent?: LoadingFinishedEvent;
|
||||
loadingFailedEvent?: LoadingFailedEvent;
|
||||
};
|
||||
export type FetchRequestId = string;
|
||||
type NetworkRequestId = string;
|
||||
type RedirectInfo = {
|
||||
event: RequestWillBeSentEvent;
|
||||
fetchRequestId?: FetchRequestId;
|
||||
};
|
||||
export declare class NetworkEventManager {
|
||||
#private;
|
||||
forget(networkRequestId: NetworkRequestId): void;
|
||||
queueFailedLoadInfo(networkRequestId: NetworkRequestId, event: LoadingFailedEvent): void;
|
||||
getFailedLoadInfo(networkRequestId: NetworkRequestId): LoadingFailedEvent | undefined;
|
||||
getResponseExtraInfo(networkRequestId: NetworkRequestId): ResponseReceivedExtraInfoEvent[];
|
||||
private queuedRedirectInfo;
|
||||
queueRedirectInfo(fetchRequestId: FetchRequestId, redirectInfo: RedirectInfo): void;
|
||||
takeQueuedRedirectInfo(fetchRequestId: FetchRequestId): RedirectInfo | undefined;
|
||||
storeRequestWillBeSent(networkRequestId: NetworkRequestId, event: RequestWillBeSentEvent): void;
|
||||
getRequestWillBeSent(networkRequestId: NetworkRequestId): RequestWillBeSentEvent | undefined;
|
||||
forgetRequestWillBeSent(networkRequestId: NetworkRequestId): void;
|
||||
storeRequestPaused(networkRequestId: NetworkRequestId, event: RequestPausedEvent): void;
|
||||
getRequest(networkRequestId: NetworkRequestId): HTTPRequest | undefined;
|
||||
storeRequest(networkRequestId: NetworkRequestId, request: HTTPRequest): void;
|
||||
forgetRequest(networkRequestId: NetworkRequestId): void;
|
||||
getQueuedEventGroup(networkRequestId: NetworkRequestId): QueuedEventGroup | undefined;
|
||||
queueEventGroup(networkRequestId: NetworkRequestId, event: QueuedEventGroup): void;
|
||||
forgetQueuedEventGroup(networkRequestId: NetworkRequestId): void;
|
||||
}
|
||||
export {};
|
||||
Generated
Vendored
+76
@@ -0,0 +1,76 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.NetworkEventManager = void 0;
|
||||
class NetworkEventManager {
|
||||
#requestWillBeSentMap = new Map();
|
||||
#requestPausedMap = new Map();
|
||||
#httpRequestsMap = new Map();
|
||||
#responseReceivedExtraInfoMap = new Map();
|
||||
#queuedRedirectInfoMap = new Map();
|
||||
#queuedEventGroupMap = new Map();
|
||||
#failedLoadInfoMap = new Map();
|
||||
forget(networkRequestId) {
|
||||
this.#requestWillBeSentMap.delete(networkRequestId);
|
||||
this.#requestPausedMap.delete(networkRequestId);
|
||||
this.#queuedEventGroupMap.delete(networkRequestId);
|
||||
this.#queuedRedirectInfoMap.delete(networkRequestId);
|
||||
this.#responseReceivedExtraInfoMap.delete(networkRequestId);
|
||||
this.#failedLoadInfoMap.delete(networkRequestId);
|
||||
}
|
||||
queueFailedLoadInfo(networkRequestId, event) {
|
||||
this.#failedLoadInfoMap.set(networkRequestId, { event });
|
||||
}
|
||||
getFailedLoadInfo(networkRequestId) {
|
||||
var _a;
|
||||
return (_a = this.#failedLoadInfoMap.get(networkRequestId)) === null || _a === void 0 ? void 0 : _a.event;
|
||||
}
|
||||
getResponseExtraInfo(networkRequestId) {
|
||||
if (!this.#responseReceivedExtraInfoMap.has(networkRequestId)) {
|
||||
this.#responseReceivedExtraInfoMap.set(networkRequestId, []);
|
||||
}
|
||||
return this.#responseReceivedExtraInfoMap.get(networkRequestId);
|
||||
}
|
||||
queuedRedirectInfo(fetchRequestId) {
|
||||
if (!this.#queuedRedirectInfoMap.has(fetchRequestId)) {
|
||||
this.#queuedRedirectInfoMap.set(fetchRequestId, []);
|
||||
}
|
||||
return this.#queuedRedirectInfoMap.get(fetchRequestId);
|
||||
}
|
||||
queueRedirectInfo(fetchRequestId, redirectInfo) {
|
||||
this.queuedRedirectInfo(fetchRequestId).push(redirectInfo);
|
||||
}
|
||||
takeQueuedRedirectInfo(fetchRequestId) {
|
||||
return this.queuedRedirectInfo(fetchRequestId).shift();
|
||||
}
|
||||
storeRequestWillBeSent(networkRequestId, event) {
|
||||
this.#requestWillBeSentMap.set(networkRequestId, event);
|
||||
}
|
||||
getRequestWillBeSent(networkRequestId) {
|
||||
return this.#requestWillBeSentMap.get(networkRequestId);
|
||||
}
|
||||
forgetRequestWillBeSent(networkRequestId) {
|
||||
this.#requestWillBeSentMap.delete(networkRequestId);
|
||||
}
|
||||
storeRequestPaused(networkRequestId, event) {
|
||||
this.#requestPausedMap.set(networkRequestId, event);
|
||||
}
|
||||
getRequest(networkRequestId) {
|
||||
return this.#httpRequestsMap.get(networkRequestId);
|
||||
}
|
||||
storeRequest(networkRequestId, request) {
|
||||
this.#httpRequestsMap.set(networkRequestId, request);
|
||||
}
|
||||
forgetRequest(networkRequestId) {
|
||||
this.#httpRequestsMap.delete(networkRequestId);
|
||||
}
|
||||
getQueuedEventGroup(networkRequestId) {
|
||||
return this.#queuedEventGroupMap.get(networkRequestId);
|
||||
}
|
||||
queueEventGroup(networkRequestId, event) {
|
||||
this.#queuedEventGroupMap.set(networkRequestId, event);
|
||||
}
|
||||
forgetQueuedEventGroup(networkRequestId) {
|
||||
this.#queuedEventGroupMap.delete(networkRequestId);
|
||||
}
|
||||
}
|
||||
exports.NetworkEventManager = NetworkEventManager;
|
||||
Generated
Vendored
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
import type { LogLevel } from '../log-level';
|
||||
import type { Commands } from './devtools-commands';
|
||||
import { EventEmitter } from './EventEmitter';
|
||||
import type { Frame } from './FrameManager';
|
||||
export declare const NetworkManagerEmittedEvents: {
|
||||
readonly Request: symbol;
|
||||
};
|
||||
interface CDPSession extends EventEmitter {
|
||||
send<T extends keyof Commands>(method: T, ...paramArgs: Commands[T]['paramsType']): Promise<{
|
||||
value: Commands[T]['returnType'];
|
||||
size: number;
|
||||
}>;
|
||||
}
|
||||
interface FrameManager {
|
||||
frame(frameId: string): Frame | null;
|
||||
}
|
||||
export declare class NetworkManager extends EventEmitter {
|
||||
#private;
|
||||
constructor(client: CDPSession, frameManager: FrameManager, indent: boolean, logLevel: LogLevel);
|
||||
initialize(): Promise<void>;
|
||||
}
|
||||
export {};
|
||||
Generated
Vendored
+253
@@ -0,0 +1,253 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.NetworkManager = exports.NetworkManagerEmittedEvents = void 0;
|
||||
const EventEmitter_1 = require("./EventEmitter");
|
||||
const handle_failed_resource_1 = require("./handle-failed-resource");
|
||||
const HTTPRequest_1 = require("./HTTPRequest");
|
||||
const HTTPResponse_1 = require("./HTTPResponse");
|
||||
const NetworkEventManager_1 = require("./NetworkEventManager");
|
||||
exports.NetworkManagerEmittedEvents = {
|
||||
Request: Symbol('NetworkManager.Request'),
|
||||
};
|
||||
class NetworkManager extends EventEmitter_1.EventEmitter {
|
||||
#client;
|
||||
#frameManager;
|
||||
#networkEventManager = new NetworkEventManager_1.NetworkEventManager();
|
||||
#indent;
|
||||
#logLevel;
|
||||
constructor(client, frameManager, indent, logLevel) {
|
||||
super();
|
||||
this.#client = client;
|
||||
this.#frameManager = frameManager;
|
||||
this.#indent = indent;
|
||||
this.#logLevel = logLevel;
|
||||
this.#client.on('Fetch.requestPaused', this.#onRequestPaused.bind(this));
|
||||
this.#client.on('Network.requestWillBeSent', this.#onRequestWillBeSent.bind(this));
|
||||
this.#client.on('Network.requestServedFromCache', this.#onRequestServedFromCache.bind(this));
|
||||
this.#client.on('Network.responseReceived', this.#onResponseReceived.bind(this));
|
||||
this.#client.on('Network.loadingFinished', this.#onLoadingFinished.bind(this));
|
||||
this.#client.on('Network.loadingFailed', this.#onLoadingFailed.bind(this));
|
||||
this.#client.on('Network.responseReceivedExtraInfo', this.#onResponseReceivedExtraInfo.bind(this));
|
||||
}
|
||||
async initialize() {
|
||||
await this.#client.send('Network.enable');
|
||||
}
|
||||
#onRequestWillBeSent(event) {
|
||||
this.#onRequest(event, undefined);
|
||||
}
|
||||
/**
|
||||
* CDP may send a Fetch.requestPaused without or before a
|
||||
* Network.requestWillBeSent
|
||||
*
|
||||
* CDP may send multiple Fetch.requestPaused
|
||||
* for the same Network.requestWillBeSent.
|
||||
*/
|
||||
#onRequestPaused(event) {
|
||||
const { networkId: networkRequestId, requestId: fetchRequestId } = event;
|
||||
if (!networkRequestId) {
|
||||
return;
|
||||
}
|
||||
const requestWillBeSentEvent = (() => {
|
||||
const _requestWillBeSentEvent = this.#networkEventManager.getRequestWillBeSent(networkRequestId);
|
||||
// redirect requests have the same `requestId`,
|
||||
if (_requestWillBeSentEvent &&
|
||||
(_requestWillBeSentEvent.request.url !== event.request.url ||
|
||||
_requestWillBeSentEvent.request.method !== event.request.method)) {
|
||||
this.#networkEventManager.forgetRequestWillBeSent(networkRequestId);
|
||||
return;
|
||||
}
|
||||
return _requestWillBeSentEvent;
|
||||
})();
|
||||
if (requestWillBeSentEvent) {
|
||||
this.#patchRequestEventHeaders(requestWillBeSentEvent, event);
|
||||
this.#onRequest(requestWillBeSentEvent, fetchRequestId);
|
||||
}
|
||||
else {
|
||||
this.#networkEventManager.storeRequestPaused(networkRequestId, event);
|
||||
}
|
||||
}
|
||||
#patchRequestEventHeaders(requestWillBeSentEvent, requestPausedEvent) {
|
||||
requestWillBeSentEvent.request.headers = {
|
||||
...requestWillBeSentEvent.request.headers,
|
||||
// includes extra headers, like: Accept, Origin
|
||||
...requestPausedEvent.request.headers,
|
||||
};
|
||||
}
|
||||
#onRequest(event, fetchRequestId) {
|
||||
if (event.redirectResponse) {
|
||||
// We want to emit a response and requestfinished for the
|
||||
// redirectResponse, but we can't do so unless we have a
|
||||
// responseExtraInfo ready to pair it up with. If we don't have any
|
||||
// responseExtraInfos saved in our queue, they we have to wait until
|
||||
// the next one to emit response and requestfinished, *and* we should
|
||||
// also wait to emit this Request too because it should come after the
|
||||
// response/requestfinished.
|
||||
let redirectResponseExtraInfo = null;
|
||||
if (event.redirectHasExtraInfo) {
|
||||
redirectResponseExtraInfo = this.#networkEventManager
|
||||
.getResponseExtraInfo(event.requestId)
|
||||
.shift();
|
||||
if (!redirectResponseExtraInfo) {
|
||||
this.#networkEventManager.queueRedirectInfo(event.requestId, {
|
||||
event,
|
||||
fetchRequestId,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
const _request = this.#networkEventManager.getRequest(event.requestId);
|
||||
// If we connect late to the target, we could have missed the
|
||||
// requestWillBeSent event.
|
||||
if (_request) {
|
||||
this.#handleRequestRedirect(_request, event.redirectResponse, redirectResponseExtraInfo);
|
||||
}
|
||||
}
|
||||
const frame = event.frameId
|
||||
? this.#frameManager.frame(event.frameId)
|
||||
: null;
|
||||
const request = new HTTPRequest_1.HTTPRequest(frame, event);
|
||||
this.#networkEventManager.storeRequest(event.requestId, request);
|
||||
this.emit(exports.NetworkManagerEmittedEvents.Request, request);
|
||||
}
|
||||
#onRequestServedFromCache(event) {
|
||||
const request = this.#networkEventManager.getRequest(event.requestId);
|
||||
if (request) {
|
||||
request._fromMemoryCache = true;
|
||||
}
|
||||
}
|
||||
#handleRequestRedirect(request, responsePayload, extraInfo) {
|
||||
const response = new HTTPResponse_1.HTTPResponse(responsePayload, extraInfo);
|
||||
request._response = response;
|
||||
this.#forgetRequest(request, false);
|
||||
}
|
||||
#emitResponseEvent(responseReceived, extraInfo) {
|
||||
const request = this.#networkEventManager.getRequest(responseReceived.requestId);
|
||||
// FileUpload sends a response without a matching request.
|
||||
if (!request) {
|
||||
return;
|
||||
}
|
||||
const response = new HTTPResponse_1.HTTPResponse(responseReceived.response, extraInfo);
|
||||
request._response = response;
|
||||
}
|
||||
#onResponseReceived(event) {
|
||||
const request = this.#networkEventManager.getRequest(event.requestId);
|
||||
let extraInfo = null;
|
||||
if (request && !request._fromMemoryCache && event.hasExtraInfo) {
|
||||
extraInfo = this.#networkEventManager
|
||||
.getResponseExtraInfo(event.requestId)
|
||||
.shift();
|
||||
if (!extraInfo) {
|
||||
// Wait until we get the corresponding ExtraInfo event.
|
||||
this.#networkEventManager.queueEventGroup(event.requestId, {
|
||||
responseReceivedEvent: event,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.#emitResponseEvent(event, extraInfo);
|
||||
}
|
||||
#onResponseReceivedExtraInfo(event) {
|
||||
// We may have skipped a redirect response/request pair due to waiting for
|
||||
// this ExtraInfo event. If so, continue that work now that we have the
|
||||
// request.
|
||||
const redirectInfo = this.#networkEventManager.takeQueuedRedirectInfo(event.requestId);
|
||||
if (redirectInfo) {
|
||||
this.#networkEventManager
|
||||
.getResponseExtraInfo(event.requestId)
|
||||
.push(event);
|
||||
this.#onRequest(redirectInfo.event, redirectInfo.fetchRequestId);
|
||||
return;
|
||||
}
|
||||
// We may have skipped response and loading events because we didn't have
|
||||
// this ExtraInfo event yet. If so, emit those events now.
|
||||
const queuedEvents = this.#networkEventManager.getQueuedEventGroup(event.requestId);
|
||||
if (queuedEvents) {
|
||||
this.#networkEventManager.forgetQueuedEventGroup(event.requestId);
|
||||
this.#emitResponseEvent(queuedEvents.responseReceivedEvent, event);
|
||||
if (queuedEvents.loadingFinishedEvent) {
|
||||
this.#emitLoadingFinished(queuedEvents.loadingFinishedEvent);
|
||||
}
|
||||
if (queuedEvents.loadingFailedEvent) {
|
||||
this.#emitLoadingFailed(queuedEvents.loadingFailedEvent);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Wait until we get another event that can use this ExtraInfo event.
|
||||
this.#networkEventManager.getResponseExtraInfo(event.requestId).push(event);
|
||||
}
|
||||
#forgetRequest(request, events) {
|
||||
const requestId = request._requestId;
|
||||
this.#networkEventManager.forgetRequest(requestId);
|
||||
if (events) {
|
||||
this.#networkEventManager.forget(requestId);
|
||||
}
|
||||
}
|
||||
#onLoadingFinished(event) {
|
||||
// If the response event for this request is still waiting on a
|
||||
// corresponding ExtraInfo event, then wait to emit this event too.
|
||||
const queuedEvents = this.#networkEventManager.getQueuedEventGroup(event.requestId);
|
||||
if (queuedEvents) {
|
||||
queuedEvents.loadingFinishedEvent = event;
|
||||
}
|
||||
else {
|
||||
this.#emitLoadingFinished(event);
|
||||
}
|
||||
}
|
||||
#emitLoadingFinished(event) {
|
||||
const request = this.#networkEventManager.getRequest(event.requestId);
|
||||
// For certain requestIds we never receive requestWillBeSent event.
|
||||
// @see https://crbug.com/750469
|
||||
if (!request) {
|
||||
return;
|
||||
}
|
||||
this.#forgetRequest(request, true);
|
||||
}
|
||||
#onLoadingFailed(event) {
|
||||
// If the response event for this request is still waiting on a
|
||||
// corresponding ExtraInfo event, then wait to emit this event too.
|
||||
const queuedEvents = this.#networkEventManager.getQueuedEventGroup(event.requestId);
|
||||
if (queuedEvents) {
|
||||
queuedEvents.loadingFailedEvent = event;
|
||||
}
|
||||
else {
|
||||
this.#emitLoadingFailed(event);
|
||||
}
|
||||
}
|
||||
#emitLoadingFailed(event) {
|
||||
const request = this.#networkEventManager.getRequest(event.requestId);
|
||||
// For certain requestIds we never receive requestWillBeSent event.
|
||||
// @see https://crbug.com/750469
|
||||
if (!request) {
|
||||
return;
|
||||
}
|
||||
if (event.canceled) {
|
||||
this.#forgetRequest(request, true);
|
||||
return;
|
||||
}
|
||||
const extraInfo = this.#networkEventManager.getResponseExtraInfo(event.requestId);
|
||||
(0, handle_failed_resource_1.handleFailedResource)({
|
||||
extraInfo,
|
||||
event,
|
||||
indent: this.#indent,
|
||||
logLevel: this.#logLevel,
|
||||
request,
|
||||
});
|
||||
this.#forgetRequest(request, true);
|
||||
}
|
||||
}
|
||||
exports.NetworkManager = NetworkManager;
|
||||
Generated
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
import type { WS } from '../ws/ws-types';
|
||||
interface ConnectionTransport {
|
||||
send(message: string): void;
|
||||
close(): void;
|
||||
onmessage?: (message: string) => void;
|
||||
onclose?: () => void;
|
||||
}
|
||||
export declare class NodeWebSocketTransport implements ConnectionTransport {
|
||||
static create(urlString: string): Promise<NodeWebSocketTransport>;
|
||||
websocket: WS;
|
||||
onmessage?: (message: string) => void;
|
||||
onclose?: () => void;
|
||||
constructor(ws: WS);
|
||||
send(message: string): void;
|
||||
close(): void;
|
||||
forgetEventLoop(): void;
|
||||
rememberEventLoop(): void;
|
||||
}
|
||||
export {};
|
||||
Generated
Vendored
+84
@@ -0,0 +1,84 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.NodeWebSocketTransport = void 0;
|
||||
/**
|
||||
* Copyright 2018 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.
|
||||
*/
|
||||
const node_dns_1 = require("node:dns");
|
||||
const node_url_1 = require("node:url");
|
||||
const ws_types_1 = require("../ws/ws-types");
|
||||
class NodeWebSocketTransport {
|
||||
static async create(urlString) {
|
||||
// Starting in Node 17, IPv6 is favoured over IPv4 due to a change
|
||||
// in a default option:
|
||||
// - https://github.com/nodejs/node/issues/40537,
|
||||
// Due to this, for Firefox, we must parse and resolve the `localhost` hostname
|
||||
// manually with the previous behavior according to:
|
||||
// - https://nodejs.org/api/dns.html#dnslookuphostname-options-callback
|
||||
// because of https://bugzilla.mozilla.org/show_bug.cgi?id=1769994.
|
||||
const url = new node_url_1.URL(urlString);
|
||||
if (url.hostname === 'localhost') {
|
||||
const { address } = await node_dns_1.promises.lookup(url.hostname, { verbatim: false });
|
||||
url.hostname = address;
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const ws = new ws_types_1.ws(url, [], {
|
||||
followRedirects: true,
|
||||
perMessageDeflate: false,
|
||||
maxPayload: 1024 * 1024 * 1024, // 1024Mb
|
||||
headers: {
|
||||
'User-Agent': `Remotion CLI`,
|
||||
},
|
||||
});
|
||||
ws.addEventListener('open', () => {
|
||||
return resolve(new NodeWebSocketTransport(ws));
|
||||
});
|
||||
ws.addEventListener('error', reject);
|
||||
});
|
||||
}
|
||||
websocket;
|
||||
onmessage;
|
||||
onclose;
|
||||
constructor(ws) {
|
||||
this.websocket = ws;
|
||||
this.websocket.addEventListener('message', (event) => {
|
||||
if (this.onmessage) {
|
||||
this.onmessage.call(null, event.data);
|
||||
}
|
||||
});
|
||||
this.websocket.addEventListener('close', () => {
|
||||
if (this.onclose) {
|
||||
this.onclose.call(null);
|
||||
}
|
||||
});
|
||||
// Silently ignore all errors - we don't know what to do with them.
|
||||
this.websocket.addEventListener('error', () => undefined);
|
||||
}
|
||||
send(message) {
|
||||
this.websocket.send(message);
|
||||
}
|
||||
close() {
|
||||
this.websocket.close();
|
||||
}
|
||||
forgetEventLoop() {
|
||||
// @ts-expect-error
|
||||
this.websocket._socket.unref();
|
||||
}
|
||||
rememberEventLoop() {
|
||||
// @ts-expect-error
|
||||
this.websocket._socket.ref();
|
||||
}
|
||||
}
|
||||
exports.NodeWebSocketTransport = NodeWebSocketTransport;
|
||||
Generated
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
export interface Viewport {
|
||||
width: number;
|
||||
height: number;
|
||||
deviceScaleFactor: number;
|
||||
}
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
Generated
Vendored
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
"use strict";
|
||||
Generated
Vendored
+72
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
import { BrowserLog } from '../browser-log';
|
||||
import type { LogLevel } from '../log-level';
|
||||
import type { BrowserContext, HeadlessBrowser } from './Browser';
|
||||
import { OnLog, Page } from './BrowserPage';
|
||||
import type { CDPSession } from './Connection';
|
||||
import type { TargetInfo } from './devtools-types';
|
||||
import type { Viewport } from './PuppeteerViewport';
|
||||
import type { SourceMapGetter } from './source-map-getter';
|
||||
export declare class Target {
|
||||
#private;
|
||||
_initializedPromise: Promise<boolean> | null;
|
||||
_initializedCallback: (x: boolean) => void;
|
||||
_isClosedPromise: Promise<void>;
|
||||
_closedCallback: () => void;
|
||||
_isInitialized: boolean;
|
||||
_targetId: string;
|
||||
constructor(targetInfo: TargetInfo, browserContext: BrowserContext, sessionFactory: () => Promise<CDPSession>, defaultViewport: Viewport);
|
||||
/**
|
||||
* Creates a Chrome Devtools Protocol session attached to the target.
|
||||
*/
|
||||
createCDPSession(): Promise<CDPSession>;
|
||||
_getTargetInfo(): TargetInfo;
|
||||
/**
|
||||
* If the target is not of type `"page"` or `"background_page"`, returns `null`.
|
||||
*/
|
||||
page({ sourceMapGetter, logLevel, indent, pageIndex, onBrowserLog, onLog }: {
|
||||
sourceMapGetter: SourceMapGetter;
|
||||
logLevel: LogLevel;
|
||||
indent: boolean;
|
||||
pageIndex: number;
|
||||
onBrowserLog: null | ((log: BrowserLog) => void);
|
||||
onLog: OnLog;
|
||||
}): Promise<Page | null>;
|
||||
expectPage(): Promise<Page | null>;
|
||||
url(): string;
|
||||
/**
|
||||
* Identifies what kind of target this is.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* See {@link https://developer.chrome.com/extensions/background_pages | docs} for more info about background pages.
|
||||
*/
|
||||
type(): 'page' | 'background_page' | 'service_worker' | 'shared_worker' | 'other' | 'browser' | 'webview';
|
||||
/**
|
||||
* Get the browser the target belongs to.
|
||||
*/
|
||||
browser(): HeadlessBrowser;
|
||||
/**
|
||||
* Get the browser context the target belongs to.
|
||||
*/
|
||||
browserContext(): BrowserContext;
|
||||
/**
|
||||
* Get the target that opened this target. Top-level targets return `null`.
|
||||
*/
|
||||
opener(): Target | undefined;
|
||||
_targetInfoChanged(targetInfo: TargetInfo): void;
|
||||
}
|
||||
Generated
Vendored
+154
@@ -0,0 +1,154 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Target = void 0;
|
||||
const BrowserPage_1 = require("./BrowserPage");
|
||||
const isPagetTarget = (target) => {
|
||||
return (target.type === 'page' ||
|
||||
target.type === 'background_page' ||
|
||||
target.type === 'webview');
|
||||
};
|
||||
class Target {
|
||||
#browserContext;
|
||||
#targetInfo;
|
||||
#sessionFactory;
|
||||
#defaultViewport;
|
||||
#pagePromise;
|
||||
_initializedPromise;
|
||||
_initializedCallback;
|
||||
_isClosedPromise;
|
||||
_closedCallback;
|
||||
_isInitialized;
|
||||
_targetId;
|
||||
constructor(targetInfo, browserContext, sessionFactory, defaultViewport) {
|
||||
this.#targetInfo = targetInfo;
|
||||
this.#browserContext = browserContext;
|
||||
this._targetId = targetInfo.targetId;
|
||||
this.#sessionFactory = sessionFactory;
|
||||
this.#defaultViewport = defaultViewport;
|
||||
this._initializedPromise = new Promise((fulfill) => {
|
||||
this._initializedCallback = fulfill;
|
||||
}).then((success) => {
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
const opener = this.opener();
|
||||
if (!opener || !opener.#pagePromise || this.type() !== 'page') {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
this._isClosedPromise = new Promise((fulfill) => {
|
||||
this._closedCallback = fulfill;
|
||||
});
|
||||
this._isInitialized =
|
||||
!isPagetTarget(this.#targetInfo) || this.#targetInfo.url !== '';
|
||||
if (this._isInitialized) {
|
||||
this._initializedCallback(true);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Creates a Chrome Devtools Protocol session attached to the target.
|
||||
*/
|
||||
createCDPSession() {
|
||||
return this.#sessionFactory();
|
||||
}
|
||||
_getTargetInfo() {
|
||||
return this.#targetInfo;
|
||||
}
|
||||
/**
|
||||
* If the target is not of type `"page"` or `"background_page"`, returns `null`.
|
||||
*/
|
||||
async page({ sourceMapGetter, logLevel, indent, pageIndex, onBrowserLog, onLog, }) {
|
||||
var _a;
|
||||
if (isPagetTarget(this.#targetInfo) && !this.#pagePromise) {
|
||||
this.#pagePromise = this.#sessionFactory().then((client) => {
|
||||
var _a;
|
||||
return BrowserPage_1.Page._create({
|
||||
client,
|
||||
target: this,
|
||||
defaultViewport: (_a = this.#defaultViewport) !== null && _a !== void 0 ? _a : null,
|
||||
browser: this.browser(),
|
||||
sourceMapGetter,
|
||||
logLevel,
|
||||
indent,
|
||||
pageIndex,
|
||||
onBrowserLog,
|
||||
onLog,
|
||||
});
|
||||
});
|
||||
}
|
||||
return (_a = (await this.#pagePromise)) !== null && _a !== void 0 ? _a : null;
|
||||
}
|
||||
async expectPage() {
|
||||
var _a;
|
||||
return (_a = (await this.#pagePromise)) !== null && _a !== void 0 ? _a : null;
|
||||
}
|
||||
url() {
|
||||
return this.#targetInfo.url;
|
||||
}
|
||||
/**
|
||||
* Identifies what kind of target this is.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* See {@link https://developer.chrome.com/extensions/background_pages | docs} for more info about background pages.
|
||||
*/
|
||||
type() {
|
||||
const { type } = this.#targetInfo;
|
||||
if (type === 'page' ||
|
||||
type === 'background_page' ||
|
||||
type === 'service_worker' ||
|
||||
type === 'shared_worker' ||
|
||||
type === 'browser' ||
|
||||
type === 'webview') {
|
||||
return type;
|
||||
}
|
||||
return 'other';
|
||||
}
|
||||
/**
|
||||
* Get the browser the target belongs to.
|
||||
*/
|
||||
browser() {
|
||||
return this.#browserContext.browser();
|
||||
}
|
||||
/**
|
||||
* Get the browser context the target belongs to.
|
||||
*/
|
||||
browserContext() {
|
||||
return this.#browserContext;
|
||||
}
|
||||
/**
|
||||
* Get the target that opened this target. Top-level targets return `null`.
|
||||
*/
|
||||
opener() {
|
||||
const { openerId } = this.#targetInfo;
|
||||
if (!openerId) {
|
||||
return;
|
||||
}
|
||||
return this.browser()._targets.get(openerId);
|
||||
}
|
||||
_targetInfoChanged(targetInfo) {
|
||||
this.#targetInfo = targetInfo;
|
||||
if (!this._isInitialized &&
|
||||
(!isPagetTarget(this.#targetInfo) || this.#targetInfo.url !== '')) {
|
||||
this._isInitialized = true;
|
||||
this._initializedCallback(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.Target = Target;
|
||||
Generated
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
export declare class TaskQueue {
|
||||
#private;
|
||||
constructor();
|
||||
postTask<T>(task: () => Promise<T>): Promise<T>;
|
||||
}
|
||||
Generated
Vendored
+34
@@ -0,0 +1,34 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TaskQueue = void 0;
|
||||
class TaskQueue {
|
||||
#chain;
|
||||
constructor() {
|
||||
this.#chain = Promise.resolve();
|
||||
}
|
||||
postTask(task) {
|
||||
const result = this.#chain.then(task);
|
||||
this.#chain = result.then(() => {
|
||||
return undefined;
|
||||
}, () => {
|
||||
return undefined;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
exports.TaskQueue = TaskQueue;
|
||||
Generated
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
export declare const DEFAULT_TIMEOUT = 30000;
|
||||
export declare class TimeoutSettings {
|
||||
#private;
|
||||
constructor();
|
||||
setDefaultTimeout(timeout: number): void;
|
||||
setDefaultNavigationTimeout(timeout: number): void;
|
||||
navigationTimeout(): number;
|
||||
timeout(): number;
|
||||
}
|
||||
Generated
Vendored
+49
@@ -0,0 +1,49 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TimeoutSettings = exports.DEFAULT_TIMEOUT = void 0;
|
||||
exports.DEFAULT_TIMEOUT = 30000;
|
||||
class TimeoutSettings {
|
||||
#defaultTimeout;
|
||||
#defaultNavigationTimeout;
|
||||
constructor() {
|
||||
this.#defaultTimeout = null;
|
||||
this.#defaultNavigationTimeout = null;
|
||||
}
|
||||
setDefaultTimeout(timeout) {
|
||||
this.#defaultTimeout = timeout;
|
||||
}
|
||||
setDefaultNavigationTimeout(timeout) {
|
||||
this.#defaultNavigationTimeout = timeout;
|
||||
}
|
||||
navigationTimeout() {
|
||||
if (this.#defaultNavigationTimeout !== null) {
|
||||
return this.#defaultNavigationTimeout;
|
||||
}
|
||||
if (this.#defaultTimeout !== null) {
|
||||
return this.#defaultTimeout;
|
||||
}
|
||||
return exports.DEFAULT_TIMEOUT;
|
||||
}
|
||||
timeout() {
|
||||
if (this.#defaultTimeout !== null) {
|
||||
return this.#defaultTimeout;
|
||||
}
|
||||
return exports.DEFAULT_TIMEOUT;
|
||||
}
|
||||
}
|
||||
exports.TimeoutSettings = TimeoutSettings;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const assert: (value: unknown, message?: string) => asserts value;
|
||||
Generated
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.assert = void 0;
|
||||
const assert = (value, message) => {
|
||||
if (!value) {
|
||||
throw new Error(message);
|
||||
}
|
||||
};
|
||||
exports.assert = assert;
|
||||
Generated
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
import type { OnBrowserDownload } from '../options/on-browser-download';
|
||||
export declare const defaultBrowserDownloadProgress: ({ indent, logLevel, api, }: {
|
||||
indent: boolean;
|
||||
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
||||
api: string;
|
||||
}) => OnBrowserDownload;
|
||||
Generated
Vendored
+31
@@ -0,0 +1,31 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.defaultBrowserDownloadProgress = void 0;
|
||||
const logger_1 = require("../logger");
|
||||
const to_megabytes_1 = require("../to-megabytes");
|
||||
const defaultBrowserDownloadProgress = ({ indent, logLevel, api, }) => ({ chromeMode }) => {
|
||||
if (chromeMode === 'chrome-for-testing') {
|
||||
logger_1.Log.info({ indent, logLevel }, 'Downloading Chrome for Testing https://www.remotion.dev/chrome-for-testing');
|
||||
}
|
||||
else {
|
||||
logger_1.Log.info({ indent, logLevel }, 'Downloading Chrome Headless Shell https://www.remotion.dev/chrome-headless-shell');
|
||||
}
|
||||
logger_1.Log.info({ indent, logLevel }, `Customize this behavior by adding a onBrowserDownload function to ${api}.`);
|
||||
let lastProgress = 0;
|
||||
return {
|
||||
onProgress: (progress) => {
|
||||
if (progress.downloadedBytes > lastProgress + 10000000 ||
|
||||
progress.percent === 1) {
|
||||
lastProgress = progress.downloadedBytes;
|
||||
if (chromeMode === 'chrome-for-testing') {
|
||||
logger_1.Log.info({ indent, logLevel }, `Downloading Chrome for Testing - ${(0, to_megabytes_1.toMegabytes)(progress.downloadedBytes)}/${(0, to_megabytes_1.toMegabytes)(progress.totalSizeInBytes)}`);
|
||||
}
|
||||
else {
|
||||
logger_1.Log.info({ indent, logLevel }, `Downloading Chrome Headless Shell - ${(0, to_megabytes_1.toMegabytes)(progress.downloadedBytes)}/${(0, to_megabytes_1.toMegabytes)(progress.totalSizeInBytes)}`);
|
||||
}
|
||||
}
|
||||
},
|
||||
version: null,
|
||||
};
|
||||
};
|
||||
exports.defaultBrowserDownloadProgress = defaultBrowserDownloadProgress;
|
||||
Generated
Vendored
+288
@@ -0,0 +1,288 @@
|
||||
import type { ActivateTargetRequest, AddScriptToEvaluateOnNewDocumentRequest, AddScriptToEvaluateOnNewDocumentResponse, CallFunctionOnRequest, CallFunctionOnResponse, CaptureScreenshotRequest, CaptureScreenshotResponse, CloseTargetRequest, CloseTargetResponse, CreateIsolatedWorldRequest, CreateIsolatedWorldResponse, DetachFromTargetRequest, DevtoolsRemoteObject, EnableRequest, ExceptionDetails, GetFrameTreeResponse, NavigateRequest, NavigateResponse, PrintPDFRequest, PrintPDFResponse, ReleaseObjectRequest, SetAutoAttachRequest, SetDefaultBackgroundColorOverrideRequest, SetDeviceMetricsOverrideRequest, SetLifecycleEventsEnabledRequest } from './devtools-types';
|
||||
export interface Commands {
|
||||
/**
|
||||
* Does nothing.
|
||||
*/
|
||||
'Console.clearMessages': {
|
||||
paramsType: [];
|
||||
returnType: void;
|
||||
};
|
||||
'Target.setDiscoverTargets': {
|
||||
paramsType: [
|
||||
{
|
||||
/**
|
||||
* Whether to discover available targets.
|
||||
*/
|
||||
discover: boolean;
|
||||
}
|
||||
];
|
||||
returnType: void;
|
||||
};
|
||||
'Target.createTarget': {
|
||||
paramsType: [
|
||||
{
|
||||
/**
|
||||
* The initial URL the page will be navigated to. An empty string indicates about:blank.
|
||||
*/
|
||||
url: string;
|
||||
/**
|
||||
* Frame width in DIP (headless chrome only).
|
||||
*/
|
||||
width?: number;
|
||||
/**
|
||||
* Frame height in DIP (headless chrome only).
|
||||
*/
|
||||
height?: number;
|
||||
/**
|
||||
* The browser context to create the page in.
|
||||
*/
|
||||
browserContextId?: string;
|
||||
/**
|
||||
* Whether BeginFrames for this target will be controlled via DevTools (headless chrome only,
|
||||
* not supported on MacOS yet, false by default).
|
||||
*/
|
||||
enableBeginFrameControl?: boolean;
|
||||
/**
|
||||
* Whether to create a new Window or Tab (chrome-only, false by default).
|
||||
*/
|
||||
newWindow?: boolean;
|
||||
/**
|
||||
* Whether to create the target in background or foreground (chrome-only,
|
||||
* false by default).
|
||||
*/
|
||||
background?: boolean;
|
||||
}
|
||||
];
|
||||
returnType: {
|
||||
targetId: string;
|
||||
};
|
||||
};
|
||||
'Browser.close': {
|
||||
paramsType: [];
|
||||
returnType: void;
|
||||
};
|
||||
'Target.attachToTarget': {
|
||||
paramsType: [
|
||||
{
|
||||
targetId: string;
|
||||
/**
|
||||
* Enables "flat" access to the session via specifying sessionId attribute in the commands.
|
||||
* We plan to make this the default, deprecate non-flattened mode,
|
||||
* and eventually retire it. See crbug.com/991325.
|
||||
*/
|
||||
flatten?: boolean;
|
||||
}
|
||||
];
|
||||
returnType: {
|
||||
/**
|
||||
* Id assigned to the session.
|
||||
*/
|
||||
sessionId: string;
|
||||
};
|
||||
};
|
||||
'Runtime.callFunctionOn': {
|
||||
paramsType: [CallFunctionOnRequest];
|
||||
returnType: CallFunctionOnResponse;
|
||||
};
|
||||
'Runtime.evaluate': {
|
||||
paramsType: [
|
||||
{
|
||||
/**
|
||||
* Expression to evaluate.
|
||||
*/
|
||||
expression: string;
|
||||
/**
|
||||
* Symbolic group name that can be used to release multiple objects.
|
||||
*/
|
||||
objectGroup?: string;
|
||||
/**
|
||||
* Determines whether Command Line API should be available during the evaluation.
|
||||
*/
|
||||
includeCommandLineAPI?: boolean;
|
||||
/**
|
||||
* In silent mode exceptions thrown during evaluation are not reported and do not pause
|
||||
* execution. Overrides `setPauseOnException` state.
|
||||
*/
|
||||
silent?: boolean;
|
||||
/**
|
||||
* Specifies in which execution context to perform evaluation. If the parameter is omitted the
|
||||
* evaluation will be performed in the context of the inspected page.
|
||||
* This is mutually exclusive with `uniqueContextId`, which offers an
|
||||
* alternative way to identify the execution context that is more reliable
|
||||
* in a multi-process environment.
|
||||
*/
|
||||
contextId?: number;
|
||||
/**
|
||||
* Whether the result is expected to be a JSON object that should be sent by value.
|
||||
*/
|
||||
returnByValue?: boolean;
|
||||
/**
|
||||
* Whether preview should be generated for the result.
|
||||
*/
|
||||
generatePreview?: boolean;
|
||||
/**
|
||||
* Whether execution should be treated as initiated by user in the UI.
|
||||
*/
|
||||
userGesture?: boolean;
|
||||
/**
|
||||
* Whether execution should `await` for resulting value and return once awaited promise is
|
||||
* resolved.
|
||||
*/
|
||||
awaitPromise?: boolean;
|
||||
/**
|
||||
* Whether to throw an exception if side effect cannot be ruled out during evaluation.
|
||||
* This implies `disableBreaks` below.
|
||||
*/
|
||||
throwOnSideEffect?: boolean;
|
||||
/**
|
||||
* Terminate execution after timing out (number of milliseconds).
|
||||
*/
|
||||
/**
|
||||
* Disable breakpoints during execution.
|
||||
*/
|
||||
disableBreaks?: boolean;
|
||||
/**
|
||||
* Setting this flag to true enables `let` re-declaration and top-level `await`.
|
||||
* Note that `let` variables can only be re-declared if they originate from
|
||||
* `replMode` themselves.
|
||||
*/
|
||||
replMode?: boolean;
|
||||
/**
|
||||
* The Content Security Policy (CSP) for the target might block 'unsafe-eval'
|
||||
* which includes eval(), Function(), setTimeout() and setInterval()
|
||||
* when called with non-callable arguments. This flag bypasses CSP for this
|
||||
* evaluation and allows unsafe-eval. Defaults to true.
|
||||
*/
|
||||
allowUnsafeEvalBlockedByCSP?: boolean;
|
||||
/**
|
||||
* An alternative way to specify the execution context to evaluate in.
|
||||
* Compared to contextId that may be reused across processes, this is guaranteed to be
|
||||
* system-unique, so it can be used to prevent accidental evaluation of the expression
|
||||
* in context different than intended (e.g. as a result of navigation across process
|
||||
* boundaries).
|
||||
* This is mutually exclusive with `contextId`.
|
||||
*/
|
||||
uniqueContextId?: string;
|
||||
/**
|
||||
* Whether the result should be serialized according to https://w3c.github.io/webdriver-bidi.
|
||||
*/
|
||||
generateWebDriverValue?: boolean;
|
||||
}
|
||||
];
|
||||
returnType: {
|
||||
/**
|
||||
* Evaluation result.
|
||||
*/
|
||||
result: DevtoolsRemoteObject;
|
||||
/**
|
||||
* Exception details.
|
||||
*/
|
||||
exceptionDetails?: ExceptionDetails;
|
||||
};
|
||||
};
|
||||
'Page.enable': {
|
||||
paramsType: [];
|
||||
returnType: void;
|
||||
};
|
||||
'Page.getFrameTree': {
|
||||
paramsType: [];
|
||||
returnType: GetFrameTreeResponse;
|
||||
};
|
||||
'Target.setAutoAttach': {
|
||||
paramsType: [SetAutoAttachRequest];
|
||||
returnType: void;
|
||||
};
|
||||
'Page.setLifecycleEventsEnabled': {
|
||||
paramsType: [SetLifecycleEventsEnabledRequest];
|
||||
returnType: void;
|
||||
};
|
||||
'Runtime.enable': {
|
||||
paramsType: [];
|
||||
returnType: void;
|
||||
};
|
||||
'Page.navigate': {
|
||||
paramsType: [NavigateRequest];
|
||||
returnType: NavigateResponse;
|
||||
};
|
||||
'Page.addScriptToEvaluateOnNewDocument': {
|
||||
paramsType: [AddScriptToEvaluateOnNewDocumentRequest];
|
||||
returnType: AddScriptToEvaluateOnNewDocumentResponse;
|
||||
};
|
||||
'Page.createIsolatedWorld': {
|
||||
paramsType: [CreateIsolatedWorldRequest];
|
||||
returnType: CreateIsolatedWorldResponse;
|
||||
};
|
||||
'Page.captureScreenshot': {
|
||||
paramsType: [CaptureScreenshotRequest?];
|
||||
returnType: CaptureScreenshotResponse;
|
||||
};
|
||||
'Page.printToPDF': {
|
||||
paramsType: [PrintPDFRequest];
|
||||
returnType: PrintPDFResponse;
|
||||
};
|
||||
'Target.activateTarget': {
|
||||
paramsType: [ActivateTargetRequest];
|
||||
returnType: void;
|
||||
};
|
||||
'Emulation.setDefaultBackgroundColorOverride': {
|
||||
paramsType: [SetDefaultBackgroundColorOverrideRequest?];
|
||||
returnType: void;
|
||||
};
|
||||
'Network.enable': {
|
||||
paramsType: [EnableRequest?];
|
||||
returnType: void;
|
||||
};
|
||||
'Target.detachFromTarget': {
|
||||
paramsType: [DetachFromTargetRequest?];
|
||||
returnType: void;
|
||||
};
|
||||
/**
|
||||
* Enable collecting and reporting metrics.
|
||||
*/
|
||||
'Performance.enable': {
|
||||
paramsType: [EnableRequest?];
|
||||
returnType: void;
|
||||
};
|
||||
'Log.enable': {
|
||||
paramsType: [];
|
||||
returnType: void;
|
||||
};
|
||||
'Page.setDeviceMetricsOverride': {
|
||||
paramsType: [SetDeviceMetricsOverrideRequest];
|
||||
returnType: void;
|
||||
};
|
||||
'Page.bringToFront': {
|
||||
paramsType: [];
|
||||
returnType: void;
|
||||
};
|
||||
'Emulation.setEmulatedMedia': {
|
||||
paramsType: [
|
||||
{
|
||||
media: 'screen';
|
||||
features: [
|
||||
{
|
||||
name: 'prefers-color-scheme';
|
||||
value: 'dark';
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
returnType: void;
|
||||
};
|
||||
'Emulation.setDeviceMetricsOverride': {
|
||||
paramsType: [SetDeviceMetricsOverrideRequest];
|
||||
returnType: void;
|
||||
};
|
||||
'Target.closeTarget': {
|
||||
paramsType: [CloseTargetRequest];
|
||||
returnType: CloseTargetResponse;
|
||||
};
|
||||
'Page.close': {
|
||||
paramsType: [];
|
||||
returnType: void;
|
||||
};
|
||||
'Runtime.releaseObject': {
|
||||
paramsType: [ReleaseObjectRequest];
|
||||
returnType: void;
|
||||
};
|
||||
}
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
Generated
Vendored
+1263
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
export declare const isTargetClosedErr: (error: Error | undefined) => boolean | undefined;
|
||||
export declare const isFlakyNetworkError: (error: Error | undefined) => boolean | undefined;
|
||||
Generated
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isFlakyNetworkError = exports.isTargetClosedErr = void 0;
|
||||
const isTargetClosedErr = (error) => {
|
||||
var _a, _b;
|
||||
return (((_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.includes('Target closed')) ||
|
||||
((_b = error === null || error === void 0 ? void 0 : error.message) === null || _b === void 0 ? void 0 : _b.includes('Session closed')));
|
||||
};
|
||||
exports.isTargetClosedErr = isTargetClosedErr;
|
||||
const isFlakyNetworkError = (error) => {
|
||||
var _a, _b, _c, _d, _e, _f, _g;
|
||||
return (((_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.includes('ERR_CONNECTION_REFUSED')) ||
|
||||
((_b = error === null || error === void 0 ? void 0 : error.message) === null || _b === void 0 ? void 0 : _b.includes('ERR_CONNECTION_RESET')) ||
|
||||
((_c = error === null || error === void 0 ? void 0 : error.message) === null || _c === void 0 ? void 0 : _c.includes('ERR_CONNECTION_TIMED_OUT')) ||
|
||||
((_d = error === null || error === void 0 ? void 0 : error.message) === null || _d === void 0 ? void 0 : _d.includes('ERR_INTERNET_DISCONNECTED')) ||
|
||||
((_e = error === null || error === void 0 ? void 0 : error.message) === null || _e === void 0 ? void 0 : _e.includes('ERR_NAME_RESOLUTION_FAILED')) ||
|
||||
((_f = error === null || error === void 0 ? void 0 : error.message) === null || _f === void 0 ? void 0 : _f.includes('ERR_ADDRESS_UNREACHABLE')) ||
|
||||
((_g = error === null || error === void 0 ? void 0 : error.message) === null || _g === void 0 ? void 0 : _g.includes('ERR_NETWORK_CHANGED')));
|
||||
};
|
||||
exports.isFlakyNetworkError = isFlakyNetworkError;
|
||||
Generated
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
import type { ChromeMode } from '../options/chrome-mode';
|
||||
export declare const TESTED_VERSION = "144.0.7559.20";
|
||||
export type Platform = 'linux64' | 'linux-arm64' | 'mac-x64' | 'mac-arm64' | 'win64';
|
||||
export declare const isAmazonLinux2023: () => boolean;
|
||||
export declare const canUseRemotionMediaBinaries: () => boolean;
|
||||
export declare function getChromeDownloadUrl({ platform, version, chromeMode }: {
|
||||
platform: Platform;
|
||||
version: string | null;
|
||||
chromeMode: ChromeMode;
|
||||
}): string;
|
||||
export declare const logDownloadUrl: ({ url, logLevel, indent, }: {
|
||||
url: string;
|
||||
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
||||
indent: boolean;
|
||||
}) => void;
|
||||
skills/remotion-prompt-video/node_modules/@remotion/renderer/dist/browser/get-chrome-download-url.js
Generated
Vendored
+147
@@ -0,0 +1,147 @@
|
||||
"use strict";
|
||||
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 () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.logDownloadUrl = exports.canUseRemotionMediaBinaries = exports.isAmazonLinux2023 = exports.TESTED_VERSION = void 0;
|
||||
exports.getChromeDownloadUrl = getChromeDownloadUrl;
|
||||
const fs = __importStar(require("node:fs"));
|
||||
const os = __importStar(require("node:os"));
|
||||
const logger_1 = require("../logger");
|
||||
exports.TESTED_VERSION = '144.0.7559.20';
|
||||
// https://github.com/microsoft/playwright/blame/e76ca6cba40c26bf22c19cf37398d2b9da9ed465/packages/playwright-core/browsers.json
|
||||
// packages/playwright-core/browsers.json
|
||||
const PLAYWRIGHT_VERSION = '1207'; // 144.0.7559.20
|
||||
const isAmazonLinux2023 = () => {
|
||||
if (os.platform() !== 'linux') {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
const osRelease = fs.readFileSync('/etc/os-release', 'utf-8');
|
||||
return (osRelease.includes('Amazon Linux') && osRelease.includes('VERSION="2023"'));
|
||||
}
|
||||
catch (_a) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
exports.isAmazonLinux2023 = isAmazonLinux2023;
|
||||
// remotion.media binaries are built on Ubuntu 24.04 which requires glibc 2.35+
|
||||
const MINIMUM_GLIBC_FOR_REMOTION_MEDIA = [2, 35];
|
||||
const getGlibcVersion = () => {
|
||||
if (process.platform !== 'linux') {
|
||||
return null;
|
||||
}
|
||||
const { report } = process;
|
||||
if (!report) {
|
||||
return null;
|
||||
}
|
||||
const rep = report.getReport();
|
||||
if (typeof rep === 'string') {
|
||||
return null;
|
||||
}
|
||||
// @ts-expect-error no types
|
||||
const { glibcVersionRuntime } = rep.header;
|
||||
if (!glibcVersionRuntime) {
|
||||
return null;
|
||||
}
|
||||
const split = glibcVersionRuntime.split('.');
|
||||
if (split.length !== 2) {
|
||||
return null;
|
||||
}
|
||||
return [Number(split[0]), Number(split[1])];
|
||||
};
|
||||
const isGlibcVersionAtLeast = (required) => {
|
||||
const version = getGlibcVersion();
|
||||
if (version === null) {
|
||||
// If we can't detect, assume it's not compatible to be safe
|
||||
return false;
|
||||
}
|
||||
const [major, minor] = version;
|
||||
const [reqMajor, reqMinor] = required;
|
||||
if (major > reqMajor) {
|
||||
return true;
|
||||
}
|
||||
if (major === reqMajor && minor >= reqMinor) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const canUseRemotionMediaBinaries = () => {
|
||||
if (process.platform !== 'linux') {
|
||||
// remotion.media binaries are only for Linux
|
||||
return false;
|
||||
}
|
||||
return isGlibcVersionAtLeast(MINIMUM_GLIBC_FOR_REMOTION_MEDIA);
|
||||
};
|
||||
exports.canUseRemotionMediaBinaries = canUseRemotionMediaBinaries;
|
||||
function getChromeDownloadUrl({ platform, version, chromeMode, }) {
|
||||
if (platform === 'linux-arm64') {
|
||||
// Amazon Linux 2023 on arm64 needs a special build.
|
||||
// This binary is compatible with older glibc (no 2.35 requirement).
|
||||
if ((0, exports.isAmazonLinux2023)() && chromeMode === 'headless-shell' && !version) {
|
||||
return 'https://remotion.media/chromium-headless-shell-amazon-linux-arm64-144.0.7559.20.zip';
|
||||
}
|
||||
if (chromeMode === 'chrome-for-testing') {
|
||||
return `https://playwright.azureedge.net/builds/chromium/${version !== null && version !== void 0 ? version : PLAYWRIGHT_VERSION}/chromium-linux-arm64.zip`;
|
||||
}
|
||||
if (version) {
|
||||
return `https://playwright.azureedge.net/builds/chromium/${version}/chromium-headless-shell-linux-arm64.zip`;
|
||||
}
|
||||
// Regular arm64 binary requires glibc 2.35+
|
||||
if ((0, exports.canUseRemotionMediaBinaries)()) {
|
||||
return `https://remotion.media/chromium-headless-shell-linux-arm64-${exports.TESTED_VERSION}.zip?clearcache`;
|
||||
}
|
||||
// Fall back to Playwright for older glibc (non-Amazon Linux systems)
|
||||
return `https://playwright.azureedge.net/builds/chromium/${PLAYWRIGHT_VERSION}/chromium-headless-shell-linux-arm64.zip`;
|
||||
}
|
||||
if (chromeMode === 'headless-shell') {
|
||||
// Amazon Linux 2023 needs a special build.
|
||||
// This binary is compatible with older glibc (no 2.35 requirement).
|
||||
if ((0, exports.isAmazonLinux2023)() && platform === 'linux64' && !version) {
|
||||
return `https://remotion.media/chromium-headless-shell-amazon-linux-x64-144.0.7559.20.zip`;
|
||||
}
|
||||
if (platform === 'linux64' && version === null) {
|
||||
if ((0, exports.canUseRemotionMediaBinaries)()) {
|
||||
return `https://remotion.media/chromium-headless-shell-linux-x64-${exports.TESTED_VERSION}.zip?clearcache`;
|
||||
}
|
||||
// Fall back to Google's CDN for older glibc
|
||||
return `https://storage.googleapis.com/chrome-for-testing-public/${exports.TESTED_VERSION}/${platform}/chrome-headless-shell-${platform}.zip`;
|
||||
}
|
||||
return `https://storage.googleapis.com/chrome-for-testing-public/${version !== null && version !== void 0 ? version : exports.TESTED_VERSION}/${platform}/chrome-headless-shell-${platform}.zip`;
|
||||
}
|
||||
return `https://storage.googleapis.com/chrome-for-testing-public/${version !== null && version !== void 0 ? version : exports.TESTED_VERSION}/${platform}/chrome-${platform}.zip`;
|
||||
}
|
||||
const logDownloadUrl = ({ url, logLevel, indent, }) => {
|
||||
logger_1.Log.info({ indent, logLevel }, `Downloading from: ${url}`);
|
||||
};
|
||||
exports.logDownloadUrl = logDownloadUrl;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const getDownloadsCacheDir: () => string;
|
||||
Generated
Vendored
+38
@@ -0,0 +1,38 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getDownloadsCacheDir = void 0;
|
||||
const node_fs_1 = __importDefault(require("node:fs"));
|
||||
const node_path_1 = __importDefault(require("node:path"));
|
||||
const getDownloadsCacheDir = () => {
|
||||
const cwd = process.cwd();
|
||||
let dir = cwd;
|
||||
for (;;) {
|
||||
try {
|
||||
if (node_fs_1.default.statSync(node_path_1.default.join(dir, 'package.json')).isFile()) {
|
||||
break;
|
||||
}
|
||||
// eslint-disable-next-line no-empty
|
||||
}
|
||||
catch (e) { }
|
||||
const parent = node_path_1.default.dirname(dir);
|
||||
if (dir === parent) {
|
||||
dir = undefined;
|
||||
break;
|
||||
}
|
||||
dir = parent;
|
||||
}
|
||||
if (!dir) {
|
||||
return node_path_1.default.resolve(cwd, '.remotion');
|
||||
}
|
||||
if (process.versions.pnp === '1') {
|
||||
return node_path_1.default.resolve(dir, '.pnp/.remotion');
|
||||
}
|
||||
if (process.versions.pnp === '3') {
|
||||
return node_path_1.default.resolve(dir, '.yarn/.remotion');
|
||||
}
|
||||
return node_path_1.default.resolve(dir, 'node_modules/.remotion');
|
||||
};
|
||||
exports.getDownloadsCacheDir = getDownloadsCacheDir;
|
||||
Generated
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
import type { HTTPRequest } from './HTTPRequest';
|
||||
import type { LoadingFailedEvent, ResponseReceivedExtraInfoEvent } from './devtools-types';
|
||||
export declare const handleFailedResource: ({ extraInfo, logLevel, indent, request, event, }: {
|
||||
extraInfo: ResponseReceivedExtraInfoEvent[];
|
||||
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
||||
indent: boolean;
|
||||
request: HTTPRequest;
|
||||
event: LoadingFailedEvent;
|
||||
}) => void;
|
||||
Generated
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.handleFailedResource = void 0;
|
||||
const logger_1 = require("../logger");
|
||||
const handleFailedResource = ({ extraInfo, logLevel, indent, request, event, }) => {
|
||||
var _a;
|
||||
var _b;
|
||||
const firstExtraInfo = (_b = extraInfo[0]) !== null && _b !== void 0 ? _b : null;
|
||||
logger_1.Log.warn({ indent, logLevel }, `Browser failed to load ${request._url} (${event.type}): ${event.errorText}`);
|
||||
if (firstExtraInfo) {
|
||||
logger_1.Log.warn({ indent, logLevel }, `HTTP status code: ${firstExtraInfo.statusCode}, headers:`);
|
||||
logger_1.Log.warn({ indent, logLevel }, JSON.stringify(firstExtraInfo.headers, null, 2));
|
||||
}
|
||||
if (event.errorText === 'net::ERR_FAILED' &&
|
||||
event.type === 'Fetch' &&
|
||||
((_a = request._url) === null || _a === void 0 ? void 0 : _a.includes('/proxy'))) {
|
||||
logger_1.Log.warn({ indent, logLevel }, 'This could be caused by Chrome rejecting the request because the disk space is low.');
|
||||
logger_1.Log.warn({ indent, logLevel }, 'This could be caused by Chrome rejecting the request because the disk space is low.');
|
||||
logger_1.Log.warn({ indent, logLevel }, 'Consider increasing the disk size of your Lambda function.');
|
||||
}
|
||||
};
|
||||
exports.handleFailedResource = handleFailedResource;
|
||||
Generated
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
export type EventType = string | symbol;
|
||||
export type Handler<T = any> = (event?: T) => void;
|
||||
type WildcardHandler = (type: EventType, event?: any) => void;
|
||||
type EventHandlerList = Array<Handler>;
|
||||
type WildCardEventHandlerList = Array<WildcardHandler>;
|
||||
type EventHandlerMap = Map<EventType, EventHandlerList | WildCardEventHandlerList>;
|
||||
export interface Emitter {
|
||||
all: EventHandlerMap;
|
||||
on<T = any>(type: EventType, handler: Handler<T>): void;
|
||||
on(type: '*', handler: WildcardHandler): void;
|
||||
off<T = any>(type: EventType, handler: Handler<T>): void;
|
||||
off(type: '*', handler: WildcardHandler): void;
|
||||
emit<T = any>(type: EventType, event?: T): void;
|
||||
emit(type: '*', event?: any): void;
|
||||
}
|
||||
/**
|
||||
* Mitt: Tiny (~200b) functional event emitter / pubsub.
|
||||
* @name mitt
|
||||
* @returns {Mitt}
|
||||
*/
|
||||
export default function mitt(all?: EventHandlerMap): Emitter;
|
||||
export {};
|
||||
Generated
Vendored
+49
@@ -0,0 +1,49 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.default = mitt;
|
||||
/**
|
||||
* Mitt: Tiny (~200b) functional event emitter / pubsub.
|
||||
* @name mitt
|
||||
* @returns {Mitt}
|
||||
*/
|
||||
function mitt(all) {
|
||||
all = all || new Map();
|
||||
return {
|
||||
/**
|
||||
* A Map of event names to registered handler functions.
|
||||
*/
|
||||
all,
|
||||
/**
|
||||
* Register an event handler for the given type.
|
||||
* @param {string|symbol} type Type of event to listen for, or `"*"` for all events
|
||||
* @param {Function} handler Function to call in response to given event
|
||||
* @memberOf mitt
|
||||
*/
|
||||
on: (type, handler) => {
|
||||
const handlers = all === null || all === void 0 ? void 0 : all.get(type);
|
||||
const added = handlers === null || handlers === void 0 ? void 0 : handlers.push(handler);
|
||||
if (!added) {
|
||||
all === null || all === void 0 ? void 0 : all.set(type, [handler]);
|
||||
}
|
||||
},
|
||||
off: (type, handler) => {
|
||||
const handlers = all === null || all === void 0 ? void 0 : all.get(type);
|
||||
if (handlers) {
|
||||
// eslint-disable-next-line no-bitwise
|
||||
handlers.splice(handlers.indexOf(handler) >>> 0, 1);
|
||||
}
|
||||
},
|
||||
emit: (type, evt) => {
|
||||
((all === null || all === void 0 ? void 0 : all.get(type)) || [])
|
||||
.slice()
|
||||
.forEach((handler) => {
|
||||
handler(evt);
|
||||
});
|
||||
((all === null || all === void 0 ? void 0 : all.get('*')) || [])
|
||||
.slice()
|
||||
.forEach((handler) => {
|
||||
handler(type, evt);
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
Generated
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
type ParsedBrowserLogMessage = {
|
||||
day: number;
|
||||
month: number;
|
||||
hour: number;
|
||||
minute: number;
|
||||
seconds: number;
|
||||
microseconds: number;
|
||||
level: string;
|
||||
location: string;
|
||||
lineNumber: number;
|
||||
message: string;
|
||||
};
|
||||
export declare const parseBrowserLogMessage: (input: string) => ParsedBrowserLogMessage | null;
|
||||
export {};
|
||||
Generated
Vendored
+38
@@ -0,0 +1,38 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseBrowserLogMessage = void 0;
|
||||
const parseBrowserLogMessage = (input) => {
|
||||
var _a;
|
||||
// Chrome <144: [MMDD/HHMMSS.UUUUUU:LEVEL:LOCATION(LINE)] message
|
||||
// Chrome 144+: [MMDD/HHMMSS.UUUUUU:LEVEL:LOCATION:LINE] message
|
||||
const format = /^\[([0-9]{4})\/([0-9]{6})\.([0-9]{6}):([A-Z]+):(.*?)(?:\(([0-9]+)\)|:([0-9]+))\](.*)/;
|
||||
const match = input.match(format);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
const date = match[1];
|
||||
const day = parseInt(date.slice(0, 2), 10);
|
||||
const month = parseInt(date.slice(2, 4), 10);
|
||||
const time = match[2];
|
||||
const hour = parseInt(time.slice(0, 2), 10);
|
||||
const minute = parseInt(time.slice(2, 4), 10);
|
||||
const seconds = parseInt(time.slice(4, 6), 10);
|
||||
const microseconds = parseInt(match[3], 10);
|
||||
const level = match[4];
|
||||
const location = match[5];
|
||||
const lineNumber = parseInt((_a = match[6]) !== null && _a !== void 0 ? _a : match[7], 10);
|
||||
const message = match[8].trim();
|
||||
return {
|
||||
day,
|
||||
month,
|
||||
hour,
|
||||
minute,
|
||||
seconds,
|
||||
microseconds,
|
||||
level,
|
||||
location,
|
||||
lineNumber,
|
||||
message,
|
||||
};
|
||||
};
|
||||
exports.parseBrowserLogMessage = parseBrowserLogMessage;
|
||||
Generated
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
export declare const shouldLogBrowserMessage: (message: string) => boolean;
|
||||
export declare const formatChromeMessage: (input: string) => {
|
||||
output: string;
|
||||
tag: string;
|
||||
} | null;
|
||||
type ChromeLogLocation = {
|
||||
location: string;
|
||||
lineNumber: number;
|
||||
};
|
||||
export declare const parseChromeLogLocation: (message: string) => ChromeLogLocation | null;
|
||||
export {};
|
||||
Generated
Vendored
+73
@@ -0,0 +1,73 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseChromeLogLocation = exports.formatChromeMessage = exports.shouldLogBrowserMessage = void 0;
|
||||
const parse_browser_log_message_1 = require("./parse-browser-log-message");
|
||||
const shouldLogBrowserMessage = (message) => {
|
||||
// Not relevant for the user
|
||||
if (message.startsWith('DevTools listening on')) {
|
||||
return false;
|
||||
}
|
||||
// In Ubuntu GitHub Action
|
||||
if (message.includes('Falling back to ALSA for audio output')) {
|
||||
return false;
|
||||
}
|
||||
// In Ubuntu GitHub Action
|
||||
if (message.includes('Floss manager not present, cannot set Floss enable/disable')) {
|
||||
return false;
|
||||
}
|
||||
// Noisy but harmless warning
|
||||
if (message.includes('Failed to send GpuControl.CreateCommandBuffer')) {
|
||||
return false;
|
||||
}
|
||||
if (message.includes('CreatePlatformSocket() failed: Address family not supported by protocol')) {
|
||||
return false;
|
||||
}
|
||||
if (message.includes('Fontconfig error: No writable cache directories')) {
|
||||
return false;
|
||||
}
|
||||
if (message.includes('AttributionReportingCrossAppWeb cannot be enabled in this configuration')) {
|
||||
return false;
|
||||
}
|
||||
if (message.includes('Trying to Produce a Memory representation from a non-existent mailbox.')) {
|
||||
return false;
|
||||
}
|
||||
if (message.includes('Received HEADERS for invalid stream')) {
|
||||
return false;
|
||||
}
|
||||
if (message.includes('CVDisplayLinkCreateWithCGDisplay failed')) {
|
||||
return false;
|
||||
}
|
||||
if (message.includes('Falling back to ALSA for audio output')) {
|
||||
return false;
|
||||
}
|
||||
if (message.includes('VizNullHypothesis is disabled')) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
exports.shouldLogBrowserMessage = shouldLogBrowserMessage;
|
||||
const formatChromeMessage = (input) => {
|
||||
const parsed = (0, parse_browser_log_message_1.parseBrowserLogMessage)(input);
|
||||
if (!parsed) {
|
||||
return { output: input, tag: 'chrome' };
|
||||
}
|
||||
const { location, lineNumber, message } = parsed;
|
||||
// Don't print console.log's, these are handled through the WebSocket
|
||||
if (location === 'CONSOLE') {
|
||||
return null;
|
||||
}
|
||||
return { output: `${location}:${lineNumber}: ${message}`, tag: 'chrome' };
|
||||
};
|
||||
exports.formatChromeMessage = formatChromeMessage;
|
||||
const parseChromeLogLocation = (message) => {
|
||||
const regex = /(.*), source: (.*) \(([0-9]+)\)/;
|
||||
const match = message.match(regex);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
lineNumber: parseInt(match[3], 10),
|
||||
location: match[2],
|
||||
};
|
||||
};
|
||||
exports.parseChromeLogLocation = parseChromeLogLocation;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { AnySourceMapConsumer } from '../symbolicate-stacktrace';
|
||||
export type SourceMapGetter = () => AnySourceMapConsumer | null;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
Generated
Vendored
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
import type { HeadlessBrowser } from './Browser';
|
||||
import type { CDPSession } from './Connection';
|
||||
import type { DevtoolsRemoteObject, ExceptionDetails } from './devtools-types';
|
||||
import type { CommonEventEmitter } from './EventEmitter';
|
||||
export declare function getExceptionMessage(exceptionDetails: ExceptionDetails): string;
|
||||
export declare function valueFromRemoteObject(remoteObject: DevtoolsRemoteObject): any;
|
||||
export declare function releaseObject(client: CDPSession, remoteObject: DevtoolsRemoteObject): Promise<void>;
|
||||
export declare function addEventListener(emitter: CommonEventEmitter, eventName: string | symbol, handler: (...args: any[]) => void): () => CommonEventEmitter;
|
||||
export declare function removeEventListeners(listeners: Array<() => void>): void;
|
||||
export declare const isString: (obj: unknown) => obj is string;
|
||||
export declare function evaluationString(fun: Function | string, ...args: unknown[]): string;
|
||||
export declare function pageBindingDeliverResultString(name: string, seq: number, result: unknown): string;
|
||||
export declare function pageBindingDeliverErrorString(name: string, seq: number, message: string, stack?: string): string;
|
||||
export declare function pageBindingDeliverErrorValueString(name: string, seq: number, value: unknown): string;
|
||||
export declare function waitWithTimeout<T>(promise: Promise<T>, taskName: string, timeout: number, browser: HeadlessBrowser): Promise<T>;
|
||||
interface ErrorLike extends Error {
|
||||
name: string;
|
||||
message: string;
|
||||
}
|
||||
export declare function isErrorLike(obj: unknown): obj is ErrorLike;
|
||||
export declare function isErrnoException(obj: unknown): obj is NodeJS.ErrnoException;
|
||||
export {};
|
||||
Generated
Vendored
+169
@@ -0,0 +1,169 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isString = void 0;
|
||||
exports.getExceptionMessage = getExceptionMessage;
|
||||
exports.valueFromRemoteObject = valueFromRemoteObject;
|
||||
exports.releaseObject = releaseObject;
|
||||
exports.addEventListener = addEventListener;
|
||||
exports.removeEventListeners = removeEventListeners;
|
||||
exports.evaluationString = evaluationString;
|
||||
exports.pageBindingDeliverResultString = pageBindingDeliverResultString;
|
||||
exports.pageBindingDeliverErrorString = pageBindingDeliverErrorString;
|
||||
exports.pageBindingDeliverErrorValueString = pageBindingDeliverErrorValueString;
|
||||
exports.waitWithTimeout = waitWithTimeout;
|
||||
exports.isErrorLike = isErrorLike;
|
||||
exports.isErrnoException = isErrnoException;
|
||||
const assert_1 = require("./assert");
|
||||
const Errors_1 = require("./Errors");
|
||||
function getExceptionMessage(exceptionDetails) {
|
||||
if (exceptionDetails.exception) {
|
||||
return (exceptionDetails.exception.description || exceptionDetails.exception.value);
|
||||
}
|
||||
let message = exceptionDetails.text;
|
||||
if (exceptionDetails.stackTrace) {
|
||||
for (const callframe of exceptionDetails.stackTrace.callFrames) {
|
||||
const location = callframe.url +
|
||||
':' +
|
||||
callframe.lineNumber +
|
||||
':' +
|
||||
callframe.columnNumber;
|
||||
const functionName = callframe.functionName || '<anonymous>';
|
||||
message += `\n at ${functionName} (${location})`;
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
function valueFromRemoteObject(remoteObject) {
|
||||
(0, assert_1.assert)(!remoteObject.objectId, 'Cannot extract value when objectId is given');
|
||||
if (remoteObject.unserializableValue) {
|
||||
if (remoteObject.type === 'bigint' && typeof BigInt !== 'undefined') {
|
||||
return BigInt(remoteObject.unserializableValue.replace('n', ''));
|
||||
}
|
||||
switch (remoteObject.unserializableValue) {
|
||||
case '-0':
|
||||
return -0;
|
||||
case 'NaN':
|
||||
return NaN;
|
||||
case 'Infinity':
|
||||
return Infinity;
|
||||
case '-Infinity':
|
||||
return -Infinity;
|
||||
default:
|
||||
throw new Error('Unsupported unserializable value: ' +
|
||||
remoteObject.unserializableValue);
|
||||
}
|
||||
}
|
||||
return remoteObject.value;
|
||||
}
|
||||
async function releaseObject(client, remoteObject) {
|
||||
if (!remoteObject.objectId) {
|
||||
return;
|
||||
}
|
||||
await client
|
||||
.send('Runtime.releaseObject', { objectId: remoteObject.objectId })
|
||||
.catch(() => {
|
||||
// Exceptions might happen in case of a page been navigated or closed.
|
||||
// Swallow these since they are harmless and we don't leak anything in this case.
|
||||
});
|
||||
}
|
||||
function addEventListener(emitter, eventName, handler) {
|
||||
emitter.on(eventName, handler);
|
||||
return () => emitter.off(eventName, handler);
|
||||
}
|
||||
function removeEventListeners(listeners) {
|
||||
for (const listener of listeners) {
|
||||
listener();
|
||||
}
|
||||
listeners.length = 0;
|
||||
}
|
||||
const isString = (obj) => {
|
||||
return typeof obj === 'string' || obj instanceof String;
|
||||
};
|
||||
exports.isString = isString;
|
||||
function evaluationString(fun, ...args) {
|
||||
if ((0, exports.isString)(fun)) {
|
||||
(0, assert_1.assert)(args.length === 0, 'Cannot evaluate a string with arguments');
|
||||
return fun;
|
||||
}
|
||||
function serializeArgument(arg) {
|
||||
if (Object.is(arg, undefined)) {
|
||||
return 'undefined';
|
||||
}
|
||||
return JSON.stringify(arg);
|
||||
}
|
||||
return `(${fun})(${args.map(serializeArgument).join(',')})`;
|
||||
}
|
||||
function pageBindingDeliverResultString(name, seq, result) {
|
||||
function deliverResult(_name, _seq, _result) {
|
||||
window[_name].callbacks.get(_seq).resolve(_result);
|
||||
window[_name].callbacks.delete(_seq);
|
||||
}
|
||||
return evaluationString(deliverResult, name, seq, result);
|
||||
}
|
||||
function pageBindingDeliverErrorString(name, seq, message, stack) {
|
||||
function deliverError(_name, _seq, _message, _stack) {
|
||||
const error = new Error(_message);
|
||||
error.stack = _stack;
|
||||
window[_name].callbacks.get(_seq).reject(error);
|
||||
window[_name].callbacks.delete(_seq);
|
||||
}
|
||||
return evaluationString(deliverError, name, seq, message, stack);
|
||||
}
|
||||
function pageBindingDeliverErrorValueString(name, seq, value) {
|
||||
function deliverErrorValue(_name, _seq, _value) {
|
||||
window[_name].callbacks.get(_seq).reject(_value);
|
||||
window[_name].callbacks.delete(_seq);
|
||||
}
|
||||
return evaluationString(deliverErrorValue, name, seq, value);
|
||||
}
|
||||
async function waitWithTimeout(promise, taskName, timeout, browser) {
|
||||
let reject;
|
||||
const timeoutError = new Errors_1.TimeoutError(`waiting for ${taskName} failed: timeout ${timeout}ms exceeded`);
|
||||
const timeoutPromise = new Promise((_res, rej) => {
|
||||
reject = rej;
|
||||
});
|
||||
let timeoutTimer = null;
|
||||
if (timeout) {
|
||||
timeoutTimer = setTimeout(() => {
|
||||
return reject(timeoutError);
|
||||
}, timeout);
|
||||
}
|
||||
try {
|
||||
return await Promise.race([
|
||||
new Promise((_, rej) => {
|
||||
browser.once("closed" /* BrowserEmittedEvents.Closed */, () => {
|
||||
return rej();
|
||||
});
|
||||
}),
|
||||
promise,
|
||||
timeoutPromise,
|
||||
]);
|
||||
}
|
||||
finally {
|
||||
if (timeoutTimer) {
|
||||
clearTimeout(timeoutTimer);
|
||||
}
|
||||
}
|
||||
}
|
||||
function isErrorLike(obj) {
|
||||
return (typeof obj === 'object' && obj !== null && 'name' in obj && 'message' in obj);
|
||||
}
|
||||
function isErrnoException(obj) {
|
||||
return (isErrorLike(obj) &&
|
||||
('errno' in obj || 'code' in obj || 'path' in obj || 'syscall' in obj));
|
||||
}
|
||||
Reference in New Issue
Block a user