init commit
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.WebKit = void 0;
|
||||
var _wkBrowser = require("../webkit/wkBrowser");
|
||||
var _path = _interopRequireDefault(require("path"));
|
||||
var _wkConnection = require("./wkConnection");
|
||||
var _browserType = require("../browserType");
|
||||
var _stackTrace = require("../../utils/stackTrace");
|
||||
var _utils = require("../../utils");
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
class WebKit extends _browserType.BrowserType {
|
||||
constructor(parent) {
|
||||
super(parent, 'webkit');
|
||||
}
|
||||
_connectToTransport(transport, options) {
|
||||
return _wkBrowser.WKBrowser.connect(this.attribution.playwright, transport, options);
|
||||
}
|
||||
_amendEnvironment(env, userDataDir, executable, browserArguments) {
|
||||
return {
|
||||
...env,
|
||||
CURL_COOKIE_JAR_PATH: _path.default.join(userDataDir, 'cookiejar.db')
|
||||
};
|
||||
}
|
||||
_rewriteStartupError(error) {
|
||||
if (error.message.includes('cannot open display')) return (0, _stackTrace.rewriteErrorMessage)(error, '\n' + (0, _utils.wrapInASCIIBox)(_browserType.kNoXServerRunningError, 1));
|
||||
return error;
|
||||
}
|
||||
_attemptToGracefullyCloseBrowser(transport) {
|
||||
transport.send({
|
||||
method: 'Playwright.close',
|
||||
params: {},
|
||||
id: _wkConnection.kBrowserCloseMessageId
|
||||
});
|
||||
}
|
||||
_defaultArgs(options, isPersistent, userDataDir) {
|
||||
const {
|
||||
args = [],
|
||||
proxy,
|
||||
headless
|
||||
} = options;
|
||||
const userDataDirArg = args.find(arg => arg.startsWith('--user-data-dir'));
|
||||
if (userDataDirArg) throw new Error('Pass userDataDir parameter to `browserType.launchPersistentContext(userDataDir, ...)` instead of specifying --user-data-dir argument');
|
||||
if (args.find(arg => !arg.startsWith('-'))) throw new Error('Arguments can not specify page to be opened');
|
||||
const webkitArguments = ['--inspector-pipe'];
|
||||
if (process.platform === 'win32') webkitArguments.push('--disable-accelerated-compositing');
|
||||
if (headless) webkitArguments.push('--headless');
|
||||
if (isPersistent) webkitArguments.push(`--user-data-dir=${userDataDir}`);else webkitArguments.push(`--no-startup-window`);
|
||||
if (proxy) {
|
||||
if (process.platform === 'darwin') {
|
||||
webkitArguments.push(`--proxy=${proxy.server}`);
|
||||
if (proxy.bypass) webkitArguments.push(`--proxy-bypass-list=${proxy.bypass}`);
|
||||
} else if (process.platform === 'linux') {
|
||||
webkitArguments.push(`--proxy=${proxy.server}`);
|
||||
if (proxy.bypass) webkitArguments.push(...proxy.bypass.split(',').map(t => `--ignore-host=${t}`));
|
||||
} else if (process.platform === 'win32') {
|
||||
// Enable socks5 hostname resolution on Windows. Workaround can be removed once fixed upstream.
|
||||
// See https://github.com/microsoft/playwright/issues/20451
|
||||
webkitArguments.push(`--curl-proxy=${proxy.server.replace(/^socks5:\/\//, 'socks5h://')}`);
|
||||
if (proxy.bypass) webkitArguments.push(`--curl-noproxy=${proxy.bypass}`);
|
||||
}
|
||||
}
|
||||
webkitArguments.push(...args);
|
||||
if (isPersistent) webkitArguments.push('about:blank');
|
||||
return webkitArguments;
|
||||
}
|
||||
}
|
||||
exports.WebKit = WebKit;
|
||||
@@ -0,0 +1,194 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getAccessibilityTree = getAccessibilityTree;
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
async function getAccessibilityTree(session, needle) {
|
||||
const objectId = needle ? needle._objectId : undefined;
|
||||
const {
|
||||
axNode
|
||||
} = await session.send('Page.accessibilitySnapshot', {
|
||||
objectId
|
||||
});
|
||||
const tree = new WKAXNode(axNode);
|
||||
return {
|
||||
tree,
|
||||
needle: needle ? tree._findNeedle() : null
|
||||
};
|
||||
}
|
||||
const WKRoleToARIARole = new Map(Object.entries({
|
||||
'TextField': 'textbox'
|
||||
}));
|
||||
|
||||
// WebKit localizes role descriptions on mac, but the english versions only add noise.
|
||||
const WKUnhelpfulRoleDescriptions = new Map(Object.entries({
|
||||
'WebArea': 'HTML content',
|
||||
'Summary': 'summary',
|
||||
'DescriptionList': 'description list',
|
||||
'ImageMap': 'image map',
|
||||
'ListMarker': 'list marker',
|
||||
'Video': 'video playback',
|
||||
'Mark': 'highlighted',
|
||||
'contentinfo': 'content information',
|
||||
'Details': 'details',
|
||||
'DescriptionListDetail': 'description',
|
||||
'DescriptionListTerm': 'term',
|
||||
'alertdialog': 'web alert dialog',
|
||||
'dialog': 'web dialog',
|
||||
'status': 'application status',
|
||||
'tabpanel': 'tab panel',
|
||||
'application': 'web application'
|
||||
}));
|
||||
class WKAXNode {
|
||||
constructor(payload) {
|
||||
this._payload = void 0;
|
||||
this._children = void 0;
|
||||
this._payload = payload;
|
||||
this._children = [];
|
||||
for (const payload of this._payload.children || []) this._children.push(new WKAXNode(payload));
|
||||
}
|
||||
children() {
|
||||
return this._children;
|
||||
}
|
||||
_findNeedle() {
|
||||
if (this._payload.found) return this;
|
||||
for (const child of this._children) {
|
||||
const found = child._findNeedle();
|
||||
if (found) return found;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
isControl() {
|
||||
switch (this._payload.role) {
|
||||
case 'button':
|
||||
case 'checkbox':
|
||||
case 'ColorWell':
|
||||
case 'combobox':
|
||||
case 'DisclosureTriangle':
|
||||
case 'listbox':
|
||||
case 'menu':
|
||||
case 'menubar':
|
||||
case 'menuitem':
|
||||
case 'menuitemcheckbox':
|
||||
case 'menuitemradio':
|
||||
case 'radio':
|
||||
case 'scrollbar':
|
||||
case 'searchbox':
|
||||
case 'slider':
|
||||
case 'spinbutton':
|
||||
case 'switch':
|
||||
case 'tab':
|
||||
case 'textbox':
|
||||
case 'TextField':
|
||||
case 'tree':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
_isTextControl() {
|
||||
switch (this._payload.role) {
|
||||
case 'combobox':
|
||||
case 'searchfield':
|
||||
case 'textbox':
|
||||
case 'TextField':
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
_name() {
|
||||
if (this._payload.role === 'text') return this._payload.value || '';
|
||||
return this._payload.name || '';
|
||||
}
|
||||
isInteresting(insideControl) {
|
||||
const {
|
||||
role,
|
||||
focusable
|
||||
} = this._payload;
|
||||
const name = this._name();
|
||||
if (role === 'ScrollArea') return false;
|
||||
if (role === 'WebArea') return true;
|
||||
if (focusable || role === 'MenuListOption') return true;
|
||||
|
||||
// If it's not focusable but has a control role, then it's interesting.
|
||||
if (this.isControl()) return true;
|
||||
|
||||
// A non focusable child of a control is not interesting
|
||||
if (insideControl) return false;
|
||||
return this.isLeafNode() && !!name;
|
||||
}
|
||||
_hasRendundantTextChild() {
|
||||
if (this._children.length !== 1) return false;
|
||||
const child = this._children[0];
|
||||
return child._payload.role === 'text' && this._payload.name === child._payload.value;
|
||||
}
|
||||
isLeafNode() {
|
||||
if (!this._children.length) return true;
|
||||
// WebKit on Linux ignores everything inside text controls, normalize this behavior
|
||||
if (this._isTextControl()) return true;
|
||||
// WebKit for mac has text nodes inside heading, li, menuitem, a, and p nodes
|
||||
if (this._hasRendundantTextChild()) return true;
|
||||
return false;
|
||||
}
|
||||
serialize() {
|
||||
const node = {
|
||||
role: WKRoleToARIARole.get(this._payload.role) || this._payload.role,
|
||||
name: this._name()
|
||||
};
|
||||
if ('description' in this._payload && this._payload.description !== node.name) node.description = this._payload.description;
|
||||
if ('roledescription' in this._payload) {
|
||||
const roledescription = this._payload.roledescription;
|
||||
if (roledescription !== this._payload.role && WKUnhelpfulRoleDescriptions.get(this._payload.role) !== roledescription) node.roledescription = roledescription;
|
||||
}
|
||||
if ('value' in this._payload && this._payload.role !== 'text') {
|
||||
if (typeof this._payload.value === 'string') node.valueString = this._payload.value;else if (typeof this._payload.value === 'number') node.valueNumber = this._payload.value;
|
||||
}
|
||||
if ('checked' in this._payload) node.checked = this._payload.checked === 'true' ? 'checked' : this._payload.checked === 'false' ? 'unchecked' : 'mixed';
|
||||
if ('pressed' in this._payload) node.pressed = this._payload.pressed === 'true' ? 'pressed' : this._payload.pressed === 'false' ? 'released' : 'mixed';
|
||||
const userStringProperties = ['keyshortcuts', 'valuetext'];
|
||||
for (const userStringProperty of userStringProperties) {
|
||||
if (!(userStringProperty in this._payload)) continue;
|
||||
node[userStringProperty] = this._payload[userStringProperty];
|
||||
}
|
||||
const booleanProperties = ['disabled', 'expanded', 'focused', 'modal', 'multiline', 'multiselectable', 'readonly', 'required', 'selected'];
|
||||
for (const booleanProperty of booleanProperties) {
|
||||
// WebArea and ScorllArea treat focus differently than other nodes. They report whether their frame has focus,
|
||||
// not whether focus is specifically on the root node.
|
||||
if (booleanProperty === 'focused' && (this._payload.role === 'WebArea' || this._payload.role === 'ScrollArea')) continue;
|
||||
const value = this._payload[booleanProperty];
|
||||
if (!value) continue;
|
||||
node[booleanProperty] = value;
|
||||
}
|
||||
const numericalProperties = ['level', 'valuemax', 'valuemin'];
|
||||
for (const numericalProperty of numericalProperties) {
|
||||
if (!(numericalProperty in this._payload)) continue;
|
||||
node[numericalProperty] = this._payload[numericalProperty];
|
||||
}
|
||||
const tokenProperties = ['autocomplete', 'haspopup', 'invalid'];
|
||||
for (const tokenProperty of tokenProperties) {
|
||||
const value = this._payload[tokenProperty];
|
||||
if (!value || value === 'false') continue;
|
||||
node[tokenProperty] = value;
|
||||
}
|
||||
const orientationIsApplicable = new Set(['ScrollArea', 'scrollbar', 'listbox', 'combobox', 'menu', 'tree', 'separator', 'slider', 'tablist', 'toolbar']);
|
||||
if (this._payload.orientation && orientationIsApplicable.has(this._payload.role)) node.orientation = this._payload.orientation;
|
||||
return node;
|
||||
}
|
||||
}
|
||||
326
bin/pac/tools/.playwright/package/lib/server/webkit/wkBrowser.js
Normal file
326
bin/pac/tools/.playwright/package/lib/server/webkit/wkBrowser.js
Normal file
@@ -0,0 +1,326 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.WKBrowserContext = exports.WKBrowser = void 0;
|
||||
var _browser = require("../browser");
|
||||
var _browserContext = require("../browserContext");
|
||||
var _utils = require("../../utils");
|
||||
var _eventsHelper = require("../../utils/eventsHelper");
|
||||
var network = _interopRequireWildcard(require("../network"));
|
||||
var _wkConnection = require("./wkConnection");
|
||||
var _wkPage = require("./wkPage");
|
||||
var _errors = require("../../common/errors");
|
||||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
||||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
||||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* 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 DEFAULT_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Safari/605.1.15';
|
||||
const BROWSER_VERSION = '16.4';
|
||||
class WKBrowser extends _browser.Browser {
|
||||
static async connect(parent, transport, options) {
|
||||
const browser = new WKBrowser(parent, transport, options);
|
||||
if (options.__testHookOnConnectToBrowser) await options.__testHookOnConnectToBrowser();
|
||||
const promises = [browser._browserSession.send('Playwright.enable')];
|
||||
if (options.persistent) {
|
||||
var _options$persistent;
|
||||
(_options$persistent = options.persistent).userAgent || (_options$persistent.userAgent = DEFAULT_USER_AGENT);
|
||||
browser._defaultContext = new WKBrowserContext(browser, undefined, options.persistent);
|
||||
promises.push(browser._defaultContext._initialize());
|
||||
}
|
||||
await Promise.all(promises);
|
||||
return browser;
|
||||
}
|
||||
constructor(parent, transport, options) {
|
||||
super(parent, options);
|
||||
this._connection = void 0;
|
||||
this._browserSession = void 0;
|
||||
this._contexts = new Map();
|
||||
this._wkPages = new Map();
|
||||
this._eventListeners = void 0;
|
||||
this._connection = new _wkConnection.WKConnection(transport, this._onDisconnect.bind(this), options.protocolLogger, options.browserLogsCollector);
|
||||
this._browserSession = this._connection.browserSession;
|
||||
this._eventListeners = [_eventsHelper.eventsHelper.addEventListener(this._browserSession, 'Playwright.pageProxyCreated', this._onPageProxyCreated.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._browserSession, 'Playwright.pageProxyDestroyed', this._onPageProxyDestroyed.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._browserSession, 'Playwright.provisionalLoadFailed', event => this._onProvisionalLoadFailed(event)), _eventsHelper.eventsHelper.addEventListener(this._browserSession, 'Playwright.windowOpen', event => this._onWindowOpen(event)), _eventsHelper.eventsHelper.addEventListener(this._browserSession, 'Playwright.downloadCreated', this._onDownloadCreated.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._browserSession, 'Playwright.downloadFilenameSuggested', this._onDownloadFilenameSuggested.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._browserSession, 'Playwright.downloadFinished', this._onDownloadFinished.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._browserSession, 'Playwright.screencastFinished', this._onScreencastFinished.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._browserSession, _wkConnection.kPageProxyMessageReceived, this._onPageProxyMessageReceived.bind(this))];
|
||||
}
|
||||
_onDisconnect() {
|
||||
for (const wkPage of this._wkPages.values()) wkPage.dispose(true);
|
||||
for (const video of this._idToVideo.values()) video.artifact.reportFinished(_errors.kBrowserClosedError);
|
||||
this._idToVideo.clear();
|
||||
this._didClose();
|
||||
}
|
||||
async doCreateNewContext(options) {
|
||||
const createOptions = options.proxy ? {
|
||||
// Enable socks5 hostname resolution on Windows. Workaround can be removed once fixed upstream.
|
||||
// See https://github.com/microsoft/playwright/issues/20451
|
||||
proxyServer: process.platform === 'win32' ? options.proxy.server.replace(/^socks5:\/\//, 'socks5h://') : options.proxy.server,
|
||||
proxyBypassList: options.proxy.bypass
|
||||
} : undefined;
|
||||
const {
|
||||
browserContextId
|
||||
} = await this._browserSession.send('Playwright.createContext', createOptions);
|
||||
options.userAgent = options.userAgent || DEFAULT_USER_AGENT;
|
||||
const context = new WKBrowserContext(this, browserContextId, options);
|
||||
await context._initialize();
|
||||
this._contexts.set(browserContextId, context);
|
||||
return context;
|
||||
}
|
||||
contexts() {
|
||||
return Array.from(this._contexts.values());
|
||||
}
|
||||
version() {
|
||||
return BROWSER_VERSION;
|
||||
}
|
||||
userAgent() {
|
||||
return DEFAULT_USER_AGENT;
|
||||
}
|
||||
_onDownloadCreated(payload) {
|
||||
const page = this._wkPages.get(payload.pageProxyId);
|
||||
if (!page) return;
|
||||
// In some cases, e.g. blob url download, we receive only frameScheduledNavigation
|
||||
// but no signals that the navigation was canceled and replaced by download. Fix it
|
||||
// here by simulating cancelled provisional load which matches downloads from network.
|
||||
//
|
||||
// TODO: this is racy, because download might be unrelated any navigation, and we will
|
||||
// abort navgitation that is still running. We should be able to fix this by
|
||||
// instrumenting policy decision start/proceed/cancel.
|
||||
page._page._frameManager.frameAbortedNavigation(payload.frameId, 'Download is starting');
|
||||
let originPage = page._initializedPage;
|
||||
// If it's a new window download, report it on the opener page.
|
||||
if (!originPage) {
|
||||
// Resume the page creation with an error. The page will automatically close right
|
||||
// after the download begins.
|
||||
page._firstNonInitialNavigationCommittedReject(new Error('Starting new page download'));
|
||||
if (page._opener) originPage = page._opener._initializedPage;
|
||||
}
|
||||
if (!originPage) return;
|
||||
this._downloadCreated(originPage, payload.uuid, payload.url);
|
||||
}
|
||||
_onDownloadFilenameSuggested(payload) {
|
||||
this._downloadFilenameSuggested(payload.uuid, payload.suggestedFilename);
|
||||
}
|
||||
_onDownloadFinished(payload) {
|
||||
this._downloadFinished(payload.uuid, payload.error);
|
||||
}
|
||||
_onScreencastFinished(payload) {
|
||||
var _this$_takeVideo;
|
||||
(_this$_takeVideo = this._takeVideo(payload.screencastId)) === null || _this$_takeVideo === void 0 ? void 0 : _this$_takeVideo.reportFinished();
|
||||
}
|
||||
_onPageProxyCreated(event) {
|
||||
const pageProxyId = event.pageProxyId;
|
||||
let context = null;
|
||||
if (event.browserContextId) {
|
||||
// FIXME: we don't know about the default context id, so assume that all targets from
|
||||
// unknown contexts are created in the 'default' context which can in practice be represented
|
||||
// by multiple actual contexts in WebKit. Solving this properly will require adding context
|
||||
// lifecycle events.
|
||||
context = this._contexts.get(event.browserContextId) || null;
|
||||
}
|
||||
if (!context) context = this._defaultContext;
|
||||
if (!context) return;
|
||||
const pageProxySession = new _wkConnection.WKSession(this._connection, pageProxyId, `Target closed`, message => {
|
||||
this._connection.rawSend({
|
||||
...message,
|
||||
pageProxyId
|
||||
});
|
||||
});
|
||||
const opener = event.openerId ? this._wkPages.get(event.openerId) : undefined;
|
||||
const wkPage = new _wkPage.WKPage(context, pageProxySession, opener || null);
|
||||
this._wkPages.set(pageProxyId, wkPage);
|
||||
}
|
||||
_onPageProxyDestroyed(event) {
|
||||
const pageProxyId = event.pageProxyId;
|
||||
const wkPage = this._wkPages.get(pageProxyId);
|
||||
if (!wkPage) return;
|
||||
wkPage.didClose();
|
||||
wkPage.dispose(false);
|
||||
this._wkPages.delete(pageProxyId);
|
||||
}
|
||||
_onPageProxyMessageReceived(event) {
|
||||
const wkPage = this._wkPages.get(event.pageProxyId);
|
||||
if (!wkPage) return;
|
||||
wkPage.dispatchMessageToSession(event.message);
|
||||
}
|
||||
_onProvisionalLoadFailed(event) {
|
||||
const wkPage = this._wkPages.get(event.pageProxyId);
|
||||
if (!wkPage) return;
|
||||
wkPage.handleProvisionalLoadFailed(event);
|
||||
}
|
||||
_onWindowOpen(event) {
|
||||
const wkPage = this._wkPages.get(event.pageProxyId);
|
||||
if (!wkPage) return;
|
||||
wkPage.handleWindowOpen(event);
|
||||
}
|
||||
isConnected() {
|
||||
return !this._connection.isClosed();
|
||||
}
|
||||
}
|
||||
exports.WKBrowser = WKBrowser;
|
||||
class WKBrowserContext extends _browserContext.BrowserContext {
|
||||
constructor(browser, browserContextId, options) {
|
||||
super(browser, options, browserContextId);
|
||||
this._validateEmulatedViewport(options.viewport);
|
||||
this._authenticateProxyViaHeader();
|
||||
}
|
||||
async _initialize() {
|
||||
(0, _utils.assert)(!this._wkPages().length);
|
||||
const browserContextId = this._browserContextId;
|
||||
const promises = [super._initialize()];
|
||||
promises.push(this._browser._browserSession.send('Playwright.setDownloadBehavior', {
|
||||
behavior: this._options.acceptDownloads ? 'allow' : 'deny',
|
||||
downloadPath: this._browser.options.downloadsPath,
|
||||
browserContextId
|
||||
}));
|
||||
if (this._options.ignoreHTTPSErrors) promises.push(this._browser._browserSession.send('Playwright.setIgnoreCertificateErrors', {
|
||||
browserContextId,
|
||||
ignore: true
|
||||
}));
|
||||
if (this._options.locale) promises.push(this._browser._browserSession.send('Playwright.setLanguages', {
|
||||
browserContextId,
|
||||
languages: [this._options.locale]
|
||||
}));
|
||||
if (this._options.geolocation) promises.push(this.setGeolocation(this._options.geolocation));
|
||||
if (this._options.offline) promises.push(this.setOffline(this._options.offline));
|
||||
if (this._options.httpCredentials) promises.push(this.setHTTPCredentials(this._options.httpCredentials));
|
||||
await Promise.all(promises);
|
||||
}
|
||||
_wkPages() {
|
||||
return Array.from(this._browser._wkPages.values()).filter(wkPage => wkPage._browserContext === this);
|
||||
}
|
||||
pages() {
|
||||
return this._wkPages().map(wkPage => wkPage._initializedPage).filter(pageOrNull => !!pageOrNull);
|
||||
}
|
||||
async newPageDelegate() {
|
||||
(0, _browserContext.assertBrowserContextIsNotOwned)(this);
|
||||
const {
|
||||
pageProxyId
|
||||
} = await this._browser._browserSession.send('Playwright.createPage', {
|
||||
browserContextId: this._browserContextId
|
||||
});
|
||||
return this._browser._wkPages.get(pageProxyId);
|
||||
}
|
||||
async doGetCookies(urls) {
|
||||
const {
|
||||
cookies
|
||||
} = await this._browser._browserSession.send('Playwright.getAllCookies', {
|
||||
browserContextId: this._browserContextId
|
||||
});
|
||||
return network.filterCookies(cookies.map(c => {
|
||||
const copy = {
|
||||
...c
|
||||
};
|
||||
copy.expires = c.expires === -1 ? -1 : c.expires / 1000;
|
||||
delete copy.session;
|
||||
return copy;
|
||||
}), urls);
|
||||
}
|
||||
async addCookies(cookies) {
|
||||
const cc = network.rewriteCookies(cookies).map(c => ({
|
||||
...c,
|
||||
session: c.expires === -1 || c.expires === undefined,
|
||||
expires: c.expires && c.expires !== -1 ? c.expires * 1000 : c.expires
|
||||
}));
|
||||
await this._browser._browserSession.send('Playwright.setCookies', {
|
||||
cookies: cc,
|
||||
browserContextId: this._browserContextId
|
||||
});
|
||||
}
|
||||
async clearCookies() {
|
||||
await this._browser._browserSession.send('Playwright.deleteAllCookies', {
|
||||
browserContextId: this._browserContextId
|
||||
});
|
||||
}
|
||||
async doGrantPermissions(origin, permissions) {
|
||||
await Promise.all(this.pages().map(page => page._delegate._grantPermissions(origin, permissions)));
|
||||
}
|
||||
async doClearPermissions() {
|
||||
await Promise.all(this.pages().map(page => page._delegate._clearPermissions()));
|
||||
}
|
||||
async setGeolocation(geolocation) {
|
||||
(0, _browserContext.verifyGeolocation)(geolocation);
|
||||
this._options.geolocation = geolocation;
|
||||
const payload = geolocation ? {
|
||||
...geolocation,
|
||||
timestamp: Date.now()
|
||||
} : undefined;
|
||||
await this._browser._browserSession.send('Playwright.setGeolocationOverride', {
|
||||
browserContextId: this._browserContextId,
|
||||
geolocation: payload
|
||||
});
|
||||
}
|
||||
async setExtraHTTPHeaders(headers) {
|
||||
this._options.extraHTTPHeaders = headers;
|
||||
for (const page of this.pages()) await page._delegate.updateExtraHTTPHeaders();
|
||||
}
|
||||
async setUserAgent(userAgent) {
|
||||
this._options.userAgent = userAgent;
|
||||
for (const page of this.pages()) await page._delegate.updateUserAgent();
|
||||
}
|
||||
async setOffline(offline) {
|
||||
this._options.offline = offline;
|
||||
for (const page of this.pages()) await page._delegate.updateOffline();
|
||||
}
|
||||
async doSetHTTPCredentials(httpCredentials) {
|
||||
this._options.httpCredentials = httpCredentials;
|
||||
for (const page of this.pages()) await page._delegate.updateHttpCredentials();
|
||||
}
|
||||
async doAddInitScript(source) {
|
||||
for (const page of this.pages()) await page._delegate._updateBootstrapScript();
|
||||
}
|
||||
async doRemoveInitScripts() {
|
||||
for (const page of this.pages()) await page._delegate._updateBootstrapScript();
|
||||
}
|
||||
async doExposeBinding(binding) {
|
||||
for (const page of this.pages()) await page._delegate.exposeBinding(binding);
|
||||
}
|
||||
async doRemoveExposedBindings() {
|
||||
for (const page of this.pages()) await page._delegate.removeExposedBindings();
|
||||
}
|
||||
async doUpdateRequestInterception() {
|
||||
for (const page of this.pages()) await page._delegate.updateRequestInterception();
|
||||
}
|
||||
onClosePersistent() {}
|
||||
async clearCache() {
|
||||
// We use ephemeral contexts so there is no disk cache.
|
||||
await this._browser._browserSession.send('Playwright.clearMemoryCache', {
|
||||
browserContextId: this._browserContextId
|
||||
});
|
||||
}
|
||||
async doClose() {
|
||||
if (!this._browserContextId) {
|
||||
await Promise.all(this._wkPages().map(wkPage => wkPage._stopVideo()));
|
||||
// Closing persistent context should close the browser.
|
||||
await this._browser.close();
|
||||
} else {
|
||||
await this._browser._browserSession.send('Playwright.deleteContext', {
|
||||
browserContextId: this._browserContextId
|
||||
});
|
||||
this._browser._contexts.delete(this._browserContextId);
|
||||
}
|
||||
}
|
||||
async cancelDownload(uuid) {
|
||||
await this._browser._browserSession.send('Playwright.cancelDownload', {
|
||||
uuid
|
||||
});
|
||||
}
|
||||
_validateEmulatedViewport(viewportSize) {
|
||||
if (!viewportSize) return;
|
||||
if (process.platform === 'win32' && this._browser.options.headful && (viewportSize.width < 250 || viewportSize.height < 240)) throw new Error(`WebKit on Windows has a minimal viewport of 250x240.`);
|
||||
}
|
||||
}
|
||||
exports.WKBrowserContext = WKBrowserContext;
|
||||
@@ -0,0 +1,181 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.WKSession = exports.WKConnection = void 0;
|
||||
exports.createProtocolError = createProtocolError;
|
||||
exports.kPageProxyMessageReceived = exports.kBrowserCloseMessageId = void 0;
|
||||
var _events = require("events");
|
||||
var _utils = require("../../utils");
|
||||
var _stackTrace = require("../../utils/stackTrace");
|
||||
var _debugLogger = require("../../common/debugLogger");
|
||||
var _helper = require("../helper");
|
||||
var _errors = require("../../common/errors");
|
||||
var _protocolError = require("../protocolError");
|
||||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// WKPlaywright uses this special id to issue Browser.close command which we
|
||||
// should ignore.
|
||||
const kBrowserCloseMessageId = -9999;
|
||||
|
||||
// We emulate kPageProxyMessageReceived message to unify it with Browser.pageProxyCreated
|
||||
// and Browser.pageProxyDestroyed for easier management.
|
||||
exports.kBrowserCloseMessageId = kBrowserCloseMessageId;
|
||||
const kPageProxyMessageReceived = 'kPageProxyMessageReceived';
|
||||
exports.kPageProxyMessageReceived = kPageProxyMessageReceived;
|
||||
class WKConnection {
|
||||
constructor(transport, onDisconnect, protocolLogger, browserLogsCollector) {
|
||||
this._transport = void 0;
|
||||
this._onDisconnect = void 0;
|
||||
this._protocolLogger = void 0;
|
||||
this._browserLogsCollector = void 0;
|
||||
this._lastId = 0;
|
||||
this._closed = false;
|
||||
this.browserSession = void 0;
|
||||
this._transport = transport;
|
||||
this._onDisconnect = onDisconnect;
|
||||
this._protocolLogger = protocolLogger;
|
||||
this._browserLogsCollector = browserLogsCollector;
|
||||
this.browserSession = new WKSession(this, '', _errors.kBrowserClosedError, message => {
|
||||
this.rawSend(message);
|
||||
});
|
||||
this._transport.onmessage = this._dispatchMessage.bind(this);
|
||||
// onclose should be set last, since it can be immediately called.
|
||||
this._transport.onclose = this._onClose.bind(this);
|
||||
}
|
||||
nextMessageId() {
|
||||
return ++this._lastId;
|
||||
}
|
||||
rawSend(message) {
|
||||
this._protocolLogger('send', message);
|
||||
this._transport.send(message);
|
||||
}
|
||||
_dispatchMessage(message) {
|
||||
this._protocolLogger('receive', message);
|
||||
if (message.id === kBrowserCloseMessageId) return;
|
||||
if (message.pageProxyId) {
|
||||
const payload = {
|
||||
message: message,
|
||||
pageProxyId: message.pageProxyId
|
||||
};
|
||||
this.browserSession.dispatchMessage({
|
||||
method: kPageProxyMessageReceived,
|
||||
params: payload
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.browserSession.dispatchMessage(message);
|
||||
}
|
||||
_onClose() {
|
||||
this._closed = true;
|
||||
this._transport.onmessage = undefined;
|
||||
this._transport.onclose = undefined;
|
||||
this.browserSession.dispose(true);
|
||||
this._onDisconnect();
|
||||
}
|
||||
isClosed() {
|
||||
return this._closed;
|
||||
}
|
||||
close() {
|
||||
if (!this._closed) this._transport.close();
|
||||
}
|
||||
}
|
||||
exports.WKConnection = WKConnection;
|
||||
class WKSession extends _events.EventEmitter {
|
||||
constructor(connection, sessionId, errorText, rawSend) {
|
||||
super();
|
||||
this.connection = void 0;
|
||||
this.errorText = void 0;
|
||||
this.sessionId = void 0;
|
||||
this._disposed = false;
|
||||
this._rawSend = void 0;
|
||||
this._callbacks = new Map();
|
||||
this._crashed = false;
|
||||
this.on = void 0;
|
||||
this.addListener = void 0;
|
||||
this.off = void 0;
|
||||
this.removeListener = void 0;
|
||||
this.once = void 0;
|
||||
this.setMaxListeners(0);
|
||||
this.connection = connection;
|
||||
this.sessionId = sessionId;
|
||||
this._rawSend = rawSend;
|
||||
this.errorText = errorText;
|
||||
this.on = super.on;
|
||||
this.off = super.removeListener;
|
||||
this.addListener = super.addListener;
|
||||
this.removeListener = super.removeListener;
|
||||
this.once = super.once;
|
||||
}
|
||||
async send(method, params) {
|
||||
if (this._crashed) throw new _protocolError.ProtocolError(true, 'Target crashed');
|
||||
if (this._disposed) throw new _protocolError.ProtocolError(true, `Target closed`);
|
||||
const id = this.connection.nextMessageId();
|
||||
const messageObj = {
|
||||
id,
|
||||
method,
|
||||
params
|
||||
};
|
||||
this._rawSend(messageObj);
|
||||
return new Promise((resolve, reject) => {
|
||||
this._callbacks.set(id, {
|
||||
resolve,
|
||||
reject,
|
||||
error: new _protocolError.ProtocolError(false),
|
||||
method
|
||||
});
|
||||
});
|
||||
}
|
||||
sendMayFail(method, params) {
|
||||
return this.send(method, params).catch(error => _debugLogger.debugLogger.log('error', error));
|
||||
}
|
||||
markAsCrashed() {
|
||||
this._crashed = true;
|
||||
}
|
||||
isDisposed() {
|
||||
return this._disposed;
|
||||
}
|
||||
dispose(disconnected) {
|
||||
if (disconnected) this.errorText = 'Browser closed.' + _helper.helper.formatBrowserLogs(this.connection._browserLogsCollector.recentLogs());
|
||||
for (const callback of this._callbacks.values()) {
|
||||
callback.error.sessionClosed = true;
|
||||
callback.reject((0, _stackTrace.rewriteErrorMessage)(callback.error, this.errorText));
|
||||
}
|
||||
this._callbacks.clear();
|
||||
this._disposed = true;
|
||||
}
|
||||
dispatchMessage(object) {
|
||||
if (object.id && this._callbacks.has(object.id)) {
|
||||
const callback = this._callbacks.get(object.id);
|
||||
this._callbacks.delete(object.id);
|
||||
if (object.error) callback.reject(createProtocolError(callback.error, callback.method, object.error));else callback.resolve(object.result);
|
||||
} else if (object.id && !object.error) {
|
||||
// Response might come after session has been disposed and rejected all callbacks.
|
||||
(0, _utils.assert)(this.isDisposed());
|
||||
} else {
|
||||
Promise.resolve().then(() => this.emit(object.method, object.params));
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.WKSession = WKSession;
|
||||
function createProtocolError(error, method, protocolError) {
|
||||
let message = `Protocol error (${method}): ${protocolError.message}`;
|
||||
if ('data' in protocolError) message += ` ${JSON.stringify(protocolError.data)}`;
|
||||
return (0, _stackTrace.rewriteErrorMessage)(error, message);
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.WKExecutionContext = void 0;
|
||||
var js = _interopRequireWildcard(require("../javascript"));
|
||||
var _utilityScriptSerializers = require("../isomorphic/utilityScriptSerializers");
|
||||
var _protocolError = require("../protocolError");
|
||||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
||||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
||||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
class WKExecutionContext {
|
||||
constructor(session, contextId) {
|
||||
this._session = void 0;
|
||||
this._contextId = void 0;
|
||||
this._session = session;
|
||||
this._contextId = contextId;
|
||||
}
|
||||
async rawEvaluateJSON(expression) {
|
||||
try {
|
||||
const response = await this._session.send('Runtime.evaluate', {
|
||||
expression,
|
||||
contextId: this._contextId,
|
||||
returnByValue: true
|
||||
});
|
||||
if (response.wasThrown) throw new js.JavaScriptErrorInEvaluate(response.result.description);
|
||||
return response.result.value;
|
||||
} catch (error) {
|
||||
throw rewriteError(error);
|
||||
}
|
||||
}
|
||||
async rawEvaluateHandle(expression) {
|
||||
try {
|
||||
const response = await this._session.send('Runtime.evaluate', {
|
||||
expression,
|
||||
contextId: this._contextId,
|
||||
returnByValue: false
|
||||
});
|
||||
if (response.wasThrown) throw new js.JavaScriptErrorInEvaluate(response.result.description);
|
||||
return response.result.objectId;
|
||||
} catch (error) {
|
||||
throw rewriteError(error);
|
||||
}
|
||||
}
|
||||
rawCallFunctionNoReply(func, ...args) {
|
||||
this._session.send('Runtime.callFunctionOn', {
|
||||
functionDeclaration: func.toString(),
|
||||
objectId: args.find(a => a instanceof js.JSHandle)._objectId,
|
||||
arguments: args.map(a => a instanceof js.JSHandle ? {
|
||||
objectId: a._objectId
|
||||
} : {
|
||||
value: a
|
||||
}),
|
||||
returnByValue: true,
|
||||
emulateUserGesture: true
|
||||
}).catch(() => {});
|
||||
}
|
||||
async evaluateWithArguments(expression, returnByValue, utilityScript, values, objectIds) {
|
||||
try {
|
||||
const response = await this._session.send('Runtime.callFunctionOn', {
|
||||
functionDeclaration: expression,
|
||||
objectId: utilityScript._objectId,
|
||||
arguments: [{
|
||||
objectId: utilityScript._objectId
|
||||
}, ...values.map(value => ({
|
||||
value
|
||||
})), ...objectIds.map(objectId => ({
|
||||
objectId
|
||||
}))],
|
||||
returnByValue,
|
||||
emulateUserGesture: true,
|
||||
awaitPromise: true
|
||||
});
|
||||
if (response.wasThrown) throw new js.JavaScriptErrorInEvaluate(response.result.description);
|
||||
if (returnByValue) return (0, _utilityScriptSerializers.parseEvaluationResultValue)(response.result.value);
|
||||
return utilityScript._context.createHandle(response.result);
|
||||
} catch (error) {
|
||||
throw rewriteError(error);
|
||||
}
|
||||
}
|
||||
async getProperties(context, objectId) {
|
||||
const response = await this._session.send('Runtime.getProperties', {
|
||||
objectId,
|
||||
ownProperties: true
|
||||
});
|
||||
const result = new Map();
|
||||
for (const property of response.properties) {
|
||||
if (!property.enumerable || !property.value) continue;
|
||||
result.set(property.name, context.createHandle(property.value));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
createHandle(context, remoteObject) {
|
||||
const isPromise = remoteObject.className === 'Promise';
|
||||
return new js.JSHandle(context, isPromise ? 'promise' : remoteObject.subtype || remoteObject.type, renderPreview(remoteObject), remoteObject.objectId, potentiallyUnserializableValue(remoteObject));
|
||||
}
|
||||
async releaseHandle(objectId) {
|
||||
await this._session.send('Runtime.releaseObject', {
|
||||
objectId
|
||||
});
|
||||
}
|
||||
objectCount(objectId) {
|
||||
throw new Error('Method not implemented in WebKit.');
|
||||
}
|
||||
}
|
||||
exports.WKExecutionContext = WKExecutionContext;
|
||||
function potentiallyUnserializableValue(remoteObject) {
|
||||
const value = remoteObject.value;
|
||||
const isUnserializable = remoteObject.type === 'number' && ['NaN', '-Infinity', 'Infinity', '-0'].includes(remoteObject.description);
|
||||
return isUnserializable ? js.parseUnserializableValue(remoteObject.description) : value;
|
||||
}
|
||||
function rewriteError(error) {
|
||||
if (!js.isJavaScriptErrorInEvaluate(error) && !(0, _protocolError.isSessionClosedError)(error)) return new Error('Execution context was destroyed, most likely because of a navigation.');
|
||||
return error;
|
||||
}
|
||||
function renderPreview(object) {
|
||||
if (object.type === 'undefined') return 'undefined';
|
||||
if ('value' in object) return String(object.value);
|
||||
if (object.description === 'Object' && object.preview) {
|
||||
const tokens = [];
|
||||
for (const {
|
||||
name,
|
||||
value
|
||||
} of object.preview.properties) tokens.push(`${name}: ${value}`);
|
||||
return `{${tokens.join(', ')}}`;
|
||||
}
|
||||
if (object.subtype === 'array' && object.preview) return js.sparseArrayToString(object.preview.properties);
|
||||
return object.description;
|
||||
}
|
||||
169
bin/pac/tools/.playwright/package/lib/server/webkit/wkInput.js
Normal file
169
bin/pac/tools/.playwright/package/lib/server/webkit/wkInput.js
Normal file
@@ -0,0 +1,169 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.RawTouchscreenImpl = exports.RawMouseImpl = exports.RawKeyboardImpl = void 0;
|
||||
var input = _interopRequireWildcard(require("../input"));
|
||||
var _macEditingCommands = require("../macEditingCommands");
|
||||
var _utils = require("../../utils");
|
||||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
||||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
||||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
function toModifiersMask(modifiers) {
|
||||
// From Source/WebKit/Shared/WebEvent.h
|
||||
let mask = 0;
|
||||
if (modifiers.has('Shift')) mask |= 1;
|
||||
if (modifiers.has('Control')) mask |= 2;
|
||||
if (modifiers.has('Alt')) mask |= 4;
|
||||
if (modifiers.has('Meta')) mask |= 8;
|
||||
return mask;
|
||||
}
|
||||
function toButtonsMask(buttons) {
|
||||
let mask = 0;
|
||||
if (buttons.has('left')) mask |= 1;
|
||||
if (buttons.has('right')) mask |= 2;
|
||||
if (buttons.has('middle')) mask |= 4;
|
||||
return mask;
|
||||
}
|
||||
class RawKeyboardImpl {
|
||||
constructor(session) {
|
||||
this._pageProxySession = void 0;
|
||||
this._session = void 0;
|
||||
this._pageProxySession = session;
|
||||
}
|
||||
setSession(session) {
|
||||
this._session = session;
|
||||
}
|
||||
async keydown(modifiers, code, keyCode, keyCodeWithoutLocation, key, location, autoRepeat, text) {
|
||||
const parts = [];
|
||||
for (const modifier of ['Shift', 'Control', 'Alt', 'Meta']) {
|
||||
if (modifiers.has(modifier)) parts.push(modifier);
|
||||
}
|
||||
parts.push(code);
|
||||
const shortcut = parts.join('+');
|
||||
let commands = _macEditingCommands.macEditingCommands[shortcut];
|
||||
if ((0, _utils.isString)(commands)) commands = [commands];
|
||||
await this._pageProxySession.send('Input.dispatchKeyEvent', {
|
||||
type: 'keyDown',
|
||||
modifiers: toModifiersMask(modifiers),
|
||||
windowsVirtualKeyCode: keyCode,
|
||||
code,
|
||||
key,
|
||||
text,
|
||||
unmodifiedText: text,
|
||||
autoRepeat,
|
||||
macCommands: commands,
|
||||
isKeypad: location === input.keypadLocation
|
||||
});
|
||||
}
|
||||
async keyup(modifiers, code, keyCode, keyCodeWithoutLocation, key, location) {
|
||||
await this._pageProxySession.send('Input.dispatchKeyEvent', {
|
||||
type: 'keyUp',
|
||||
modifiers: toModifiersMask(modifiers),
|
||||
key,
|
||||
windowsVirtualKeyCode: keyCode,
|
||||
code,
|
||||
isKeypad: location === input.keypadLocation
|
||||
});
|
||||
}
|
||||
async sendText(text) {
|
||||
await this._session.send('Page.insertText', {
|
||||
text
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.RawKeyboardImpl = RawKeyboardImpl;
|
||||
class RawMouseImpl {
|
||||
constructor(session) {
|
||||
this._pageProxySession = void 0;
|
||||
this._session = void 0;
|
||||
this._page = void 0;
|
||||
this._pageProxySession = session;
|
||||
}
|
||||
setSession(session) {
|
||||
this._session = session;
|
||||
}
|
||||
async move(x, y, button, buttons, modifiers, forClick) {
|
||||
await this._pageProxySession.send('Input.dispatchMouseEvent', {
|
||||
type: 'move',
|
||||
button,
|
||||
buttons: toButtonsMask(buttons),
|
||||
x,
|
||||
y,
|
||||
modifiers: toModifiersMask(modifiers)
|
||||
});
|
||||
}
|
||||
async down(x, y, button, buttons, modifiers, clickCount) {
|
||||
await this._pageProxySession.send('Input.dispatchMouseEvent', {
|
||||
type: 'down',
|
||||
button,
|
||||
buttons: toButtonsMask(buttons),
|
||||
x,
|
||||
y,
|
||||
modifiers: toModifiersMask(modifiers),
|
||||
clickCount
|
||||
});
|
||||
}
|
||||
async up(x, y, button, buttons, modifiers, clickCount) {
|
||||
await this._pageProxySession.send('Input.dispatchMouseEvent', {
|
||||
type: 'up',
|
||||
button,
|
||||
buttons: toButtonsMask(buttons),
|
||||
x,
|
||||
y,
|
||||
modifiers: toModifiersMask(modifiers),
|
||||
clickCount
|
||||
});
|
||||
}
|
||||
async wheel(x, y, buttons, modifiers, deltaX, deltaY) {
|
||||
var _this$_page;
|
||||
if ((_this$_page = this._page) !== null && _this$_page !== void 0 && _this$_page._browserContext._options.isMobile) throw new Error('Mouse wheel is not supported in mobile WebKit');
|
||||
await this._session.send('Page.updateScrollingState');
|
||||
// Wheel events hit the compositor first, so wait one frame for it to be synced.
|
||||
await this._page.mainFrame().evaluateExpression(`new Promise(requestAnimationFrame)`, {
|
||||
world: 'utility'
|
||||
});
|
||||
await this._pageProxySession.send('Input.dispatchWheelEvent', {
|
||||
x,
|
||||
y,
|
||||
deltaX,
|
||||
deltaY,
|
||||
modifiers: toModifiersMask(modifiers)
|
||||
});
|
||||
}
|
||||
setPage(page) {
|
||||
this._page = page;
|
||||
}
|
||||
}
|
||||
exports.RawMouseImpl = RawMouseImpl;
|
||||
class RawTouchscreenImpl {
|
||||
constructor(session) {
|
||||
this._pageProxySession = void 0;
|
||||
this._pageProxySession = session;
|
||||
}
|
||||
async tap(x, y, modifiers) {
|
||||
await this._pageProxySession.send('Input.dispatchTapEvent', {
|
||||
x,
|
||||
y,
|
||||
modifiers: toModifiersMask(modifiers)
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.RawTouchscreenImpl = RawTouchscreenImpl;
|
||||
@@ -0,0 +1,171 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.WKRouteImpl = exports.WKInterceptableRequest = void 0;
|
||||
var network = _interopRequireWildcard(require("../network"));
|
||||
var _utils = require("../../utils");
|
||||
var _manualPromise = require("../../utils/manualPromise");
|
||||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
||||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
||||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* 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 errorReasons = {
|
||||
'aborted': 'Cancellation',
|
||||
'accessdenied': 'AccessControl',
|
||||
'addressunreachable': 'General',
|
||||
'blockedbyclient': 'Cancellation',
|
||||
'blockedbyresponse': 'General',
|
||||
'connectionaborted': 'General',
|
||||
'connectionclosed': 'General',
|
||||
'connectionfailed': 'General',
|
||||
'connectionrefused': 'General',
|
||||
'connectionreset': 'General',
|
||||
'internetdisconnected': 'General',
|
||||
'namenotresolved': 'General',
|
||||
'timedout': 'Timeout',
|
||||
'failed': 'General'
|
||||
};
|
||||
class WKInterceptableRequest {
|
||||
constructor(session, route, frame, event, redirectedFrom, documentId) {
|
||||
this._session = void 0;
|
||||
this.request = void 0;
|
||||
this._requestId = void 0;
|
||||
this._timestamp = void 0;
|
||||
this._wallTime = void 0;
|
||||
this._route = void 0;
|
||||
this._redirectedFrom = void 0;
|
||||
this._session = session;
|
||||
this._requestId = event.requestId;
|
||||
this._route = route;
|
||||
this._redirectedFrom = redirectedFrom;
|
||||
const resourceType = event.type ? event.type.toLowerCase() : redirectedFrom ? redirectedFrom.request.resourceType() : 'other';
|
||||
let postDataBuffer = null;
|
||||
this._timestamp = event.timestamp;
|
||||
this._wallTime = event.walltime * 1000;
|
||||
if (event.request.postData) postDataBuffer = Buffer.from(event.request.postData, 'base64');
|
||||
this.request = new network.Request(frame._page._browserContext, frame, null, (redirectedFrom === null || redirectedFrom === void 0 ? void 0 : redirectedFrom.request) || null, documentId, event.request.url, resourceType, event.request.method, postDataBuffer, (0, _utils.headersObjectToArray)(event.request.headers));
|
||||
}
|
||||
_routeForRedirectChain() {
|
||||
let request = this;
|
||||
while (request._redirectedFrom) request = request._redirectedFrom;
|
||||
return request._route;
|
||||
}
|
||||
createResponse(responsePayload) {
|
||||
const getResponseBody = async () => {
|
||||
const response = await this._session.send('Network.getResponseBody', {
|
||||
requestId: this._requestId
|
||||
});
|
||||
return Buffer.from(response.body, response.base64Encoded ? 'base64' : 'utf8');
|
||||
};
|
||||
const timingPayload = responsePayload.timing;
|
||||
const timing = {
|
||||
startTime: this._wallTime,
|
||||
domainLookupStart: timingPayload ? wkMillisToRoundishMillis(timingPayload.domainLookupStart) : -1,
|
||||
domainLookupEnd: timingPayload ? wkMillisToRoundishMillis(timingPayload.domainLookupEnd) : -1,
|
||||
connectStart: timingPayload ? wkMillisToRoundishMillis(timingPayload.connectStart) : -1,
|
||||
secureConnectionStart: timingPayload ? wkMillisToRoundishMillis(timingPayload.secureConnectionStart) : -1,
|
||||
connectEnd: timingPayload ? wkMillisToRoundishMillis(timingPayload.connectEnd) : -1,
|
||||
requestStart: timingPayload ? wkMillisToRoundishMillis(timingPayload.requestStart) : -1,
|
||||
responseStart: timingPayload ? wkMillisToRoundishMillis(timingPayload.responseStart) : -1
|
||||
};
|
||||
const setCookieSeparator = process.platform === 'darwin' ? ',' : '\n';
|
||||
const response = new network.Response(this.request, responsePayload.status, responsePayload.statusText, (0, _utils.headersObjectToArray)(responsePayload.headers, ',', setCookieSeparator), timing, getResponseBody, responsePayload.source === 'service-worker');
|
||||
|
||||
// No raw response headers in WebKit, use "provisional" ones.
|
||||
response.setRawResponseHeaders(null);
|
||||
// Transfer size is not available in WebKit.
|
||||
response.setTransferSize(null);
|
||||
if (responsePayload.requestHeaders && Object.keys(responsePayload.requestHeaders).length) {
|
||||
const headers = {
|
||||
...responsePayload.requestHeaders
|
||||
};
|
||||
if (!headers['host']) headers['Host'] = new URL(this.request.url()).host;
|
||||
this.request.setRawRequestHeaders((0, _utils.headersObjectToArray)(headers));
|
||||
} else {
|
||||
// No raw headers avaialable, use provisional ones.
|
||||
this.request.setRawRequestHeaders(null);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
exports.WKInterceptableRequest = WKInterceptableRequest;
|
||||
class WKRouteImpl {
|
||||
constructor(session, requestId) {
|
||||
this._session = void 0;
|
||||
this._requestId = void 0;
|
||||
this._requestInterceptedPromise = new _manualPromise.ManualPromise();
|
||||
this._session = session;
|
||||
this._requestId = requestId;
|
||||
}
|
||||
async abort(errorCode) {
|
||||
const errorType = errorReasons[errorCode];
|
||||
(0, _utils.assert)(errorType, 'Unknown error code: ' + errorCode);
|
||||
await this._requestInterceptedPromise;
|
||||
// In certain cases, protocol will return error if the request was already canceled
|
||||
// or the page was closed. We should tolerate these errors.
|
||||
await this._session.sendMayFail('Network.interceptRequestWithError', {
|
||||
requestId: this._requestId,
|
||||
errorType
|
||||
});
|
||||
}
|
||||
async fulfill(response) {
|
||||
if (300 <= response.status && response.status < 400) throw new Error('Cannot fulfill with redirect status: ' + response.status);
|
||||
await this._requestInterceptedPromise;
|
||||
// In certain cases, protocol will return error if the request was already canceled
|
||||
// or the page was closed. We should tolerate these errors.
|
||||
let mimeType = response.isBase64 ? 'application/octet-stream' : 'text/plain';
|
||||
const headers = (0, _utils.headersArrayToObject)(response.headers, true /* lowerCase */);
|
||||
const contentType = headers['content-type'];
|
||||
if (contentType) mimeType = contentType.split(';')[0].trim();
|
||||
await this._session.sendMayFail('Network.interceptRequestWithResponse', {
|
||||
requestId: this._requestId,
|
||||
status: response.status,
|
||||
statusText: network.STATUS_TEXTS[String(response.status)],
|
||||
mimeType,
|
||||
headers,
|
||||
base64Encoded: response.isBase64,
|
||||
content: response.body
|
||||
});
|
||||
}
|
||||
async continue(request, overrides) {
|
||||
await this._requestInterceptedPromise;
|
||||
// In certain cases, protocol will return error if the request was already canceled
|
||||
// or the page was closed. We should tolerate these errors.
|
||||
await this._session.sendMayFail('Network.interceptWithRequest', {
|
||||
requestId: this._requestId,
|
||||
url: overrides.url,
|
||||
method: overrides.method,
|
||||
headers: overrides.headers ? (0, _utils.headersArrayToObject)(overrides.headers, false /* lowerCase */) : undefined,
|
||||
postData: overrides.postData ? Buffer.from(overrides.postData).toString('base64') : undefined
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.WKRouteImpl = WKRouteImpl;
|
||||
function wkMillisToRoundishMillis(value) {
|
||||
// WebKit uses -1000 for unavailable.
|
||||
if (value === -1000) return -1;
|
||||
|
||||
// WebKit has a bug, instead of -1 it sends -1000 to be in ms.
|
||||
if (value <= 0) {
|
||||
// DNS can start before request start on Mac Network Stack
|
||||
return -1;
|
||||
}
|
||||
return (value * 1000 | 0) / 1000;
|
||||
}
|
||||
1181
bin/pac/tools/.playwright/package/lib/server/webkit/wkPage.js
Normal file
1181
bin/pac/tools/.playwright/package/lib/server/webkit/wkPage.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,59 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.WKProvisionalPage = void 0;
|
||||
var _eventsHelper = require("../../utils/eventsHelper");
|
||||
var _utils = require("../../utils");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
class WKProvisionalPage {
|
||||
constructor(session, page) {
|
||||
this._session = void 0;
|
||||
this._wkPage = void 0;
|
||||
this._sessionListeners = [];
|
||||
this._mainFrameId = null;
|
||||
this.initializationPromise = void 0;
|
||||
this._session = session;
|
||||
this._wkPage = page;
|
||||
const overrideFrameId = handler => {
|
||||
return payload => {
|
||||
// Pretend that the events happened in the same process.
|
||||
if (payload.frameId) payload.frameId = this._wkPage._page._frameManager.mainFrame()._id;
|
||||
handler(payload);
|
||||
};
|
||||
};
|
||||
const wkPage = this._wkPage;
|
||||
this._sessionListeners = [_eventsHelper.eventsHelper.addEventListener(session, 'Network.requestWillBeSent', overrideFrameId(e => wkPage._onRequestWillBeSent(session, e))), _eventsHelper.eventsHelper.addEventListener(session, 'Network.requestIntercepted', overrideFrameId(e => wkPage._onRequestIntercepted(session, e))), _eventsHelper.eventsHelper.addEventListener(session, 'Network.responseReceived', overrideFrameId(e => wkPage._onResponseReceived(e))), _eventsHelper.eventsHelper.addEventListener(session, 'Network.loadingFinished', overrideFrameId(e => wkPage._onLoadingFinished(e))), _eventsHelper.eventsHelper.addEventListener(session, 'Network.loadingFailed', overrideFrameId(e => wkPage._onLoadingFailed(e)))];
|
||||
this.initializationPromise = this._wkPage._initializeSession(session, true, ({
|
||||
frameTree
|
||||
}) => this._handleFrameTree(frameTree));
|
||||
}
|
||||
dispose() {
|
||||
_eventsHelper.eventsHelper.removeEventListeners(this._sessionListeners);
|
||||
}
|
||||
commit() {
|
||||
(0, _utils.assert)(this._mainFrameId);
|
||||
this._wkPage._onFrameAttached(this._mainFrameId, null);
|
||||
}
|
||||
_handleFrameTree(frameTree) {
|
||||
(0, _utils.assert)(!frameTree.frame.parentId);
|
||||
this._mainFrameId = frameTree.frame.id;
|
||||
}
|
||||
}
|
||||
exports.WKProvisionalPage = WKProvisionalPage;
|
||||
104
bin/pac/tools/.playwright/package/lib/server/webkit/wkWorkers.js
Normal file
104
bin/pac/tools/.playwright/package/lib/server/webkit/wkWorkers.js
Normal file
@@ -0,0 +1,104 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.WKWorkers = void 0;
|
||||
var _eventsHelper = require("../../utils/eventsHelper");
|
||||
var _page = require("../page");
|
||||
var _wkConnection = require("./wkConnection");
|
||||
var _wkExecutionContext = require("./wkExecutionContext");
|
||||
/**
|
||||
* Copyright 2019 Microsoft Corporation 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.
|
||||
*/
|
||||
|
||||
class WKWorkers {
|
||||
constructor(page) {
|
||||
this._sessionListeners = [];
|
||||
this._page = void 0;
|
||||
this._workerSessions = new Map();
|
||||
this._page = page;
|
||||
}
|
||||
setSession(session) {
|
||||
_eventsHelper.eventsHelper.removeEventListeners(this._sessionListeners);
|
||||
this.clear();
|
||||
this._sessionListeners = [_eventsHelper.eventsHelper.addEventListener(session, 'Worker.workerCreated', event => {
|
||||
const worker = new _page.Worker(this._page, event.url);
|
||||
const workerSession = new _wkConnection.WKSession(session.connection, event.workerId, 'Most likely the worker has been closed.', message => {
|
||||
session.send('Worker.sendMessageToWorker', {
|
||||
workerId: event.workerId,
|
||||
message: JSON.stringify(message)
|
||||
}).catch(e => {
|
||||
workerSession.dispatchMessage({
|
||||
id: message.id,
|
||||
error: {
|
||||
message: e.message
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
this._workerSessions.set(event.workerId, workerSession);
|
||||
worker._createExecutionContext(new _wkExecutionContext.WKExecutionContext(workerSession, undefined));
|
||||
this._page._addWorker(event.workerId, worker);
|
||||
workerSession.on('Console.messageAdded', event => this._onConsoleMessage(worker, event));
|
||||
Promise.all([workerSession.send('Runtime.enable'), workerSession.send('Console.enable'), session.send('Worker.initialized', {
|
||||
workerId: event.workerId
|
||||
})]).catch(e => {
|
||||
// Worker can go as we are initializing it.
|
||||
this._page._removeWorker(event.workerId);
|
||||
});
|
||||
}), _eventsHelper.eventsHelper.addEventListener(session, 'Worker.dispatchMessageFromWorker', event => {
|
||||
const workerSession = this._workerSessions.get(event.workerId);
|
||||
if (!workerSession) return;
|
||||
workerSession.dispatchMessage(JSON.parse(event.message));
|
||||
}), _eventsHelper.eventsHelper.addEventListener(session, 'Worker.workerTerminated', event => {
|
||||
const workerSession = this._workerSessions.get(event.workerId);
|
||||
if (!workerSession) return;
|
||||
workerSession.dispose(false);
|
||||
this._workerSessions.delete(event.workerId);
|
||||
this._page._removeWorker(event.workerId);
|
||||
})];
|
||||
}
|
||||
clear() {
|
||||
this._page._clearWorkers();
|
||||
this._workerSessions.clear();
|
||||
}
|
||||
async initializeSession(session) {
|
||||
await session.send('Worker.enable');
|
||||
}
|
||||
async _onConsoleMessage(worker, event) {
|
||||
const {
|
||||
type,
|
||||
level,
|
||||
text,
|
||||
parameters,
|
||||
url,
|
||||
line: lineNumber,
|
||||
column: columnNumber
|
||||
} = event.message;
|
||||
let derivedType = type || '';
|
||||
if (type === 'log') derivedType = level;else if (type === 'timing') derivedType = 'timeEnd';
|
||||
const handles = (parameters || []).map(p => {
|
||||
return worker._existingExecutionContext.createHandle(p);
|
||||
});
|
||||
const location = {
|
||||
url: url || '',
|
||||
lineNumber: (lineNumber || 1) - 1,
|
||||
columnNumber: (columnNumber || 1) - 1
|
||||
};
|
||||
this._page._addConsoleMessage(derivedType, handles, location, handles.length ? undefined : text);
|
||||
}
|
||||
}
|
||||
exports.WKWorkers = WKWorkers;
|
||||
Reference in New Issue
Block a user