puppeteer-core
Version:
A high-level API to control headless Chrome over the DevTools Protocol
215 lines • 17.1 kB
JavaScript
/**
* 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.
*/
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _LifecycleWatcher_instances, _LifecycleWatcher_expectedLifecycle, _LifecycleWatcher_frameManager, _LifecycleWatcher_frame, _LifecycleWatcher_timeout, _LifecycleWatcher_navigationRequest, _LifecycleWatcher_eventListeners, _LifecycleWatcher_initialLoaderId, _LifecycleWatcher_sameDocumentNavigationCompleteCallback, _LifecycleWatcher_sameDocumentNavigationPromise, _LifecycleWatcher_lifecycleCallback, _LifecycleWatcher_lifecyclePromise, _LifecycleWatcher_newDocumentNavigationCompleteCallback, _LifecycleWatcher_newDocumentNavigationPromise, _LifecycleWatcher_terminationCallback, _LifecycleWatcher_terminationPromise, _LifecycleWatcher_timeoutPromise, _LifecycleWatcher_maximumTimer, _LifecycleWatcher_hasSameDocumentNavigation, _LifecycleWatcher_swapped, _LifecycleWatcher_navigationResponseReceived, _LifecycleWatcher_onRequest, _LifecycleWatcher_onRequestFailed, _LifecycleWatcher_onResponse, _LifecycleWatcher_onFrameDetached, _LifecycleWatcher_terminate, _LifecycleWatcher_createTimeoutPromise, _LifecycleWatcher_navigatedWithinDocument, _LifecycleWatcher_navigated, _LifecycleWatcher_frameSwapped, _LifecycleWatcher_checkLifecycleComplete;
import { assert } from '../util/assert.js';
import { addEventListener, removeEventListeners, } from './util.js';
import { createDeferredPromise, } from '../util/DeferredPromise.js';
import { TimeoutError } from './Errors.js';
import { FrameManagerEmittedEvents } from './FrameManager.js';
import { NetworkManagerEmittedEvents } from './NetworkManager.js';
import { CDPSessionEmittedEvents } from './Connection.js';
const puppeteerToProtocolLifecycle = new Map([
['load', 'load'],
['domcontentloaded', 'DOMContentLoaded'],
['networkidle0', 'networkIdle'],
['networkidle2', 'networkAlmostIdle'],
]);
const noop = () => { };
/**
* @internal
*/
export class LifecycleWatcher {
constructor(frameManager, frame, waitUntil, timeout) {
_LifecycleWatcher_instances.add(this);
_LifecycleWatcher_expectedLifecycle.set(this, void 0);
_LifecycleWatcher_frameManager.set(this, void 0);
_LifecycleWatcher_frame.set(this, void 0);
_LifecycleWatcher_timeout.set(this, void 0);
_LifecycleWatcher_navigationRequest.set(this, null);
_LifecycleWatcher_eventListeners.set(this, void 0);
_LifecycleWatcher_initialLoaderId.set(this, void 0);
_LifecycleWatcher_sameDocumentNavigationCompleteCallback.set(this, noop);
_LifecycleWatcher_sameDocumentNavigationPromise.set(this, new Promise(fulfill => {
__classPrivateFieldSet(this, _LifecycleWatcher_sameDocumentNavigationCompleteCallback, fulfill, "f");
}));
_LifecycleWatcher_lifecycleCallback.set(this, noop);
_LifecycleWatcher_lifecyclePromise.set(this, new Promise(fulfill => {
__classPrivateFieldSet(this, _LifecycleWatcher_lifecycleCallback, fulfill, "f");
}));
_LifecycleWatcher_newDocumentNavigationCompleteCallback.set(this, noop);
_LifecycleWatcher_newDocumentNavigationPromise.set(this, new Promise(fulfill => {
__classPrivateFieldSet(this, _LifecycleWatcher_newDocumentNavigationCompleteCallback, fulfill, "f");
}));
_LifecycleWatcher_terminationCallback.set(this, noop);
_LifecycleWatcher_terminationPromise.set(this, new Promise(fulfill => {
__classPrivateFieldSet(this, _LifecycleWatcher_terminationCallback, fulfill, "f");
}));
_LifecycleWatcher_timeoutPromise.set(this, void 0);
_LifecycleWatcher_maximumTimer.set(this, void 0);
_LifecycleWatcher_hasSameDocumentNavigation.set(this, void 0);
_LifecycleWatcher_swapped.set(this, void 0);
_LifecycleWatcher_navigationResponseReceived.set(this, void 0);
if (Array.isArray(waitUntil)) {
waitUntil = waitUntil.slice();
}
else if (typeof waitUntil === 'string') {
waitUntil = [waitUntil];
}
__classPrivateFieldSet(this, _LifecycleWatcher_initialLoaderId, frame._loaderId, "f");
__classPrivateFieldSet(this, _LifecycleWatcher_expectedLifecycle, waitUntil.map(value => {
const protocolEvent = puppeteerToProtocolLifecycle.get(value);
assert(protocolEvent, 'Unknown value for options.waitUntil: ' + value);
return protocolEvent;
}), "f");
__classPrivateFieldSet(this, _LifecycleWatcher_frameManager, frameManager, "f");
__classPrivateFieldSet(this, _LifecycleWatcher_frame, frame, "f");
__classPrivateFieldSet(this, _LifecycleWatcher_timeout, timeout, "f");
__classPrivateFieldSet(this, _LifecycleWatcher_eventListeners, [
addEventListener(frameManager.client, CDPSessionEmittedEvents.Disconnected, __classPrivateFieldGet(this, _LifecycleWatcher_instances, "m", _LifecycleWatcher_terminate).bind(this, new Error('Navigation failed because browser has disconnected!'))),
addEventListener(__classPrivateFieldGet(this, _LifecycleWatcher_frameManager, "f"), FrameManagerEmittedEvents.LifecycleEvent, __classPrivateFieldGet(this, _LifecycleWatcher_instances, "m", _LifecycleWatcher_checkLifecycleComplete).bind(this)),
addEventListener(__classPrivateFieldGet(this, _LifecycleWatcher_frameManager, "f"), FrameManagerEmittedEvents.FrameNavigatedWithinDocument, __classPrivateFieldGet(this, _LifecycleWatcher_instances, "m", _LifecycleWatcher_navigatedWithinDocument).bind(this)),
addEventListener(__classPrivateFieldGet(this, _LifecycleWatcher_frameManager, "f"), FrameManagerEmittedEvents.FrameNavigated, __classPrivateFieldGet(this, _LifecycleWatcher_instances, "m", _LifecycleWatcher_navigated).bind(this)),
addEventListener(__classPrivateFieldGet(this, _LifecycleWatcher_frameManager, "f"), FrameManagerEmittedEvents.FrameSwapped, __classPrivateFieldGet(this, _LifecycleWatcher_instances, "m", _LifecycleWatcher_frameSwapped).bind(this)),
addEventListener(__classPrivateFieldGet(this, _LifecycleWatcher_frameManager, "f"), FrameManagerEmittedEvents.FrameDetached, __classPrivateFieldGet(this, _LifecycleWatcher_instances, "m", _LifecycleWatcher_onFrameDetached).bind(this)),
addEventListener(__classPrivateFieldGet(this, _LifecycleWatcher_frameManager, "f").networkManager, NetworkManagerEmittedEvents.Request, __classPrivateFieldGet(this, _LifecycleWatcher_instances, "m", _LifecycleWatcher_onRequest).bind(this)),
addEventListener(__classPrivateFieldGet(this, _LifecycleWatcher_frameManager, "f").networkManager, NetworkManagerEmittedEvents.Response, __classPrivateFieldGet(this, _LifecycleWatcher_instances, "m", _LifecycleWatcher_onResponse).bind(this)),
addEventListener(__classPrivateFieldGet(this, _LifecycleWatcher_frameManager, "f").networkManager, NetworkManagerEmittedEvents.RequestFailed, __classPrivateFieldGet(this, _LifecycleWatcher_instances, "m", _LifecycleWatcher_onRequestFailed).bind(this)),
], "f");
__classPrivateFieldSet(this, _LifecycleWatcher_timeoutPromise, __classPrivateFieldGet(this, _LifecycleWatcher_instances, "m", _LifecycleWatcher_createTimeoutPromise).call(this), "f");
__classPrivateFieldGet(this, _LifecycleWatcher_instances, "m", _LifecycleWatcher_checkLifecycleComplete).call(this);
}
async navigationResponse() {
var _a;
// Continue with a possibly null response.
await ((_a = __classPrivateFieldGet(this, _LifecycleWatcher_navigationResponseReceived, "f")) === null || _a === void 0 ? void 0 : _a.catch(() => { }));
return __classPrivateFieldGet(this, _LifecycleWatcher_navigationRequest, "f") ? __classPrivateFieldGet(this, _LifecycleWatcher_navigationRequest, "f").response() : null;
}
sameDocumentNavigationPromise() {
return __classPrivateFieldGet(this, _LifecycleWatcher_sameDocumentNavigationPromise, "f");
}
newDocumentNavigationPromise() {
return __classPrivateFieldGet(this, _LifecycleWatcher_newDocumentNavigationPromise, "f");
}
lifecyclePromise() {
return __classPrivateFieldGet(this, _LifecycleWatcher_lifecyclePromise, "f");
}
timeoutOrTerminationPromise() {
return Promise.race([__classPrivateFieldGet(this, _LifecycleWatcher_timeoutPromise, "f"), __classPrivateFieldGet(this, _LifecycleWatcher_terminationPromise, "f")]);
}
dispose() {
removeEventListeners(__classPrivateFieldGet(this, _LifecycleWatcher_eventListeners, "f"));
__classPrivateFieldGet(this, _LifecycleWatcher_maximumTimer, "f") !== undefined && clearTimeout(__classPrivateFieldGet(this, _LifecycleWatcher_maximumTimer, "f"));
}
}
_LifecycleWatcher_expectedLifecycle = new WeakMap(), _LifecycleWatcher_frameManager = new WeakMap(), _LifecycleWatcher_frame = new WeakMap(), _LifecycleWatcher_timeout = new WeakMap(), _LifecycleWatcher_navigationRequest = new WeakMap(), _LifecycleWatcher_eventListeners = new WeakMap(), _LifecycleWatcher_initialLoaderId = new WeakMap(), _LifecycleWatcher_sameDocumentNavigationCompleteCallback = new WeakMap(), _LifecycleWatcher_sameDocumentNavigationPromise = new WeakMap(), _LifecycleWatcher_lifecycleCallback = new WeakMap(), _LifecycleWatcher_lifecyclePromise = new WeakMap(), _LifecycleWatcher_newDocumentNavigationCompleteCallback = new WeakMap(), _LifecycleWatcher_newDocumentNavigationPromise = new WeakMap(), _LifecycleWatcher_terminationCallback = new WeakMap(), _LifecycleWatcher_terminationPromise = new WeakMap(), _LifecycleWatcher_timeoutPromise = new WeakMap(), _LifecycleWatcher_maximumTimer = new WeakMap(), _LifecycleWatcher_hasSameDocumentNavigation = new WeakMap(), _LifecycleWatcher_swapped = new WeakMap(), _LifecycleWatcher_navigationResponseReceived = new WeakMap(), _LifecycleWatcher_instances = new WeakSet(), _LifecycleWatcher_onRequest = function _LifecycleWatcher_onRequest(request) {
var _a, _b;
if (request.frame() !== __classPrivateFieldGet(this, _LifecycleWatcher_frame, "f") || !request.isNavigationRequest()) {
return;
}
__classPrivateFieldSet(this, _LifecycleWatcher_navigationRequest, request, "f");
// Resolve previous navigation response in case there are multiple
// navigation requests reported by the backend. This generally should not
// happen by it looks like it's possible.
(_a = __classPrivateFieldGet(this, _LifecycleWatcher_navigationResponseReceived, "f")) === null || _a === void 0 ? void 0 : _a.resolve();
__classPrivateFieldSet(this, _LifecycleWatcher_navigationResponseReceived, createDeferredPromise(), "f");
if (request.response() !== null) {
(_b = __classPrivateFieldGet(this, _LifecycleWatcher_navigationResponseReceived, "f")) === null || _b === void 0 ? void 0 : _b.resolve();
}
}, _LifecycleWatcher_onRequestFailed = function _LifecycleWatcher_onRequestFailed(request) {
var _a, _b;
if (((_a = __classPrivateFieldGet(this, _LifecycleWatcher_navigationRequest, "f")) === null || _a === void 0 ? void 0 : _a._requestId) !== request._requestId) {
return;
}
(_b = __classPrivateFieldGet(this, _LifecycleWatcher_navigationResponseReceived, "f")) === null || _b === void 0 ? void 0 : _b.resolve();
}, _LifecycleWatcher_onResponse = function _LifecycleWatcher_onResponse(response) {
var _a, _b;
if (((_a = __classPrivateFieldGet(this, _LifecycleWatcher_navigationRequest, "f")) === null || _a === void 0 ? void 0 : _a._requestId) !== response.request()._requestId) {
return;
}
(_b = __classPrivateFieldGet(this, _LifecycleWatcher_navigationResponseReceived, "f")) === null || _b === void 0 ? void 0 : _b.resolve();
}, _LifecycleWatcher_onFrameDetached = function _LifecycleWatcher_onFrameDetached(frame) {
if (__classPrivateFieldGet(this, _LifecycleWatcher_frame, "f") === frame) {
__classPrivateFieldGet(this, _LifecycleWatcher_terminationCallback, "f").call(null, new Error('Navigating frame was detached'));
return;
}
__classPrivateFieldGet(this, _LifecycleWatcher_instances, "m", _LifecycleWatcher_checkLifecycleComplete).call(this);
}, _LifecycleWatcher_terminate = function _LifecycleWatcher_terminate(error) {
__classPrivateFieldGet(this, _LifecycleWatcher_terminationCallback, "f").call(null, error);
}, _LifecycleWatcher_createTimeoutPromise = async function _LifecycleWatcher_createTimeoutPromise() {
if (!__classPrivateFieldGet(this, _LifecycleWatcher_timeout, "f")) {
return new Promise(noop);
}
const errorMessage = 'Navigation timeout of ' + __classPrivateFieldGet(this, _LifecycleWatcher_timeout, "f") + ' ms exceeded';
await new Promise(fulfill => {
return (__classPrivateFieldSet(this, _LifecycleWatcher_maximumTimer, setTimeout(fulfill, __classPrivateFieldGet(this, _LifecycleWatcher_timeout, "f")), "f"));
});
return new TimeoutError(errorMessage);
}, _LifecycleWatcher_navigatedWithinDocument = function _LifecycleWatcher_navigatedWithinDocument(frame) {
if (frame !== __classPrivateFieldGet(this, _LifecycleWatcher_frame, "f")) {
return;
}
__classPrivateFieldSet(this, _LifecycleWatcher_hasSameDocumentNavigation, true, "f");
__classPrivateFieldGet(this, _LifecycleWatcher_instances, "m", _LifecycleWatcher_checkLifecycleComplete).call(this);
}, _LifecycleWatcher_navigated = function _LifecycleWatcher_navigated(frame) {
if (frame !== __classPrivateFieldGet(this, _LifecycleWatcher_frame, "f")) {
return;
}
__classPrivateFieldGet(this, _LifecycleWatcher_instances, "m", _LifecycleWatcher_checkLifecycleComplete).call(this);
}, _LifecycleWatcher_frameSwapped = function _LifecycleWatcher_frameSwapped(frame) {
if (frame !== __classPrivateFieldGet(this, _LifecycleWatcher_frame, "f")) {
return;
}
__classPrivateFieldSet(this, _LifecycleWatcher_swapped, true, "f");
__classPrivateFieldGet(this, _LifecycleWatcher_instances, "m", _LifecycleWatcher_checkLifecycleComplete).call(this);
}, _LifecycleWatcher_checkLifecycleComplete = function _LifecycleWatcher_checkLifecycleComplete() {
// We expect navigation to commit.
if (!checkLifecycle(__classPrivateFieldGet(this, _LifecycleWatcher_frame, "f"), __classPrivateFieldGet(this, _LifecycleWatcher_expectedLifecycle, "f"))) {
return;
}
__classPrivateFieldGet(this, _LifecycleWatcher_lifecycleCallback, "f").call(this);
if (__classPrivateFieldGet(this, _LifecycleWatcher_hasSameDocumentNavigation, "f")) {
__classPrivateFieldGet(this, _LifecycleWatcher_sameDocumentNavigationCompleteCallback, "f").call(this);
}
if (__classPrivateFieldGet(this, _LifecycleWatcher_swapped, "f") || __classPrivateFieldGet(this, _LifecycleWatcher_frame, "f")._loaderId !== __classPrivateFieldGet(this, _LifecycleWatcher_initialLoaderId, "f")) {
__classPrivateFieldGet(this, _LifecycleWatcher_newDocumentNavigationCompleteCallback, "f").call(this);
}
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;
}
};
//# sourceMappingURL=LifecycleWatcher.js.map