init commit

This commit is contained in:
iFlip721
2025-04-16 09:55:57 -04:00
commit a03209dc9e
935 changed files with 177492 additions and 0 deletions

View File

@@ -0,0 +1,193 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.AndroidSocketDispatcher = exports.AndroidDispatcher = exports.AndroidDeviceDispatcher = void 0;
var _dispatcher = require("./dispatcher");
var _android = require("../android/android");
var _browserContextDispatcher = require("./browserContextDispatcher");
/**
* 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 AndroidDispatcher extends _dispatcher.Dispatcher {
constructor(scope, android) {
super(scope, android, 'Android', {});
this._type_Android = true;
}
async devices(params) {
const devices = await this._object.devices(params);
return {
devices: devices.map(d => AndroidDeviceDispatcher.from(this, d))
};
}
async setDefaultTimeoutNoReply(params) {
this._object.setDefaultTimeout(params.timeout);
}
}
exports.AndroidDispatcher = AndroidDispatcher;
class AndroidDeviceDispatcher extends _dispatcher.Dispatcher {
static from(scope, device) {
const result = (0, _dispatcher.existingDispatcher)(device);
return result || new AndroidDeviceDispatcher(scope, device);
}
constructor(scope, device) {
super(scope, device, 'AndroidDevice', {
model: device.model,
serial: device.serial
});
this._type_EventTarget = true;
this._type_AndroidDevice = true;
for (const webView of device.webViews()) this._dispatchEvent('webViewAdded', {
webView
});
this.addObjectListener(_android.AndroidDevice.Events.WebViewAdded, webView => this._dispatchEvent('webViewAdded', {
webView
}));
this.addObjectListener(_android.AndroidDevice.Events.WebViewRemoved, socketName => this._dispatchEvent('webViewRemoved', {
socketName
}));
this.addObjectListener(_android.AndroidDevice.Events.Close, socketName => this._dispatchEvent('close'));
}
async wait(params) {
await this._object.send('wait', params);
}
async fill(params) {
await this._object.send('click', {
selector: params.selector
});
await this._object.send('fill', params);
}
async tap(params) {
await this._object.send('click', params);
}
async drag(params) {
await this._object.send('drag', params);
}
async fling(params) {
await this._object.send('fling', params);
}
async longTap(params) {
await this._object.send('longClick', params);
}
async pinchClose(params) {
await this._object.send('pinchClose', params);
}
async pinchOpen(params) {
await this._object.send('pinchOpen', params);
}
async scroll(params) {
await this._object.send('scroll', params);
}
async swipe(params) {
await this._object.send('swipe', params);
}
async info(params) {
return {
info: await this._object.send('info', params)
};
}
async inputType(params) {
const text = params.text;
const keyCodes = [];
for (let i = 0; i < text.length; ++i) {
const code = keyMap.get(text[i].toUpperCase());
if (code === undefined) throw new Error('No mapping for ' + text[i] + ' found');
keyCodes.push(code);
}
await Promise.all(keyCodes.map(keyCode => this._object.send('inputPress', {
keyCode
})));
}
async inputPress(params) {
if (!keyMap.has(params.key)) throw new Error('Unknown key: ' + params.key);
await this._object.send('inputPress', {
keyCode: keyMap.get(params.key)
});
}
async inputTap(params) {
await this._object.send('inputClick', params);
}
async inputSwipe(params) {
await this._object.send('inputSwipe', params);
}
async inputDrag(params) {
await this._object.send('inputDrag', params);
}
async screenshot(params) {
return {
binary: await this._object.screenshot()
};
}
async shell(params) {
return {
result: await this._object.shell(params.command)
};
}
async open(params, metadata) {
const socket = await this._object.open(params.command);
return {
socket: new AndroidSocketDispatcher(this, socket)
};
}
async installApk(params) {
await this._object.installApk(params.file, {
args: params.args
});
}
async push(params) {
await this._object.push(params.file, params.path, params.mode);
}
async launchBrowser(params) {
const context = await this._object.launchBrowser(params.pkg, params);
return {
context: new _browserContextDispatcher.BrowserContextDispatcher(this, context)
};
}
async close(params) {
await this._object.close();
}
async setDefaultTimeoutNoReply(params) {
this._object.setDefaultTimeout(params.timeout);
}
async connectToWebView(params) {
return {
context: new _browserContextDispatcher.BrowserContextDispatcher(this, await this._object.connectToWebView(params.socketName))
};
}
}
exports.AndroidDeviceDispatcher = AndroidDeviceDispatcher;
class AndroidSocketDispatcher extends _dispatcher.Dispatcher {
constructor(scope, socket) {
super(scope, socket, 'AndroidSocket', {});
this._type_AndroidSocket = true;
this.addObjectListener('data', data => this._dispatchEvent('data', {
data
}));
this.addObjectListener('close', () => {
this._dispatchEvent('close');
this._dispose();
});
}
async write(params, metadata) {
await this._object.write(params.data);
}
async close(params, metadata) {
this._object.close();
}
}
exports.AndroidSocketDispatcher = AndroidSocketDispatcher;
const keyMap = new Map([['Unknown', 0], ['SoftLeft', 1], ['SoftRight', 2], ['Home', 3], ['Back', 4], ['Call', 5], ['EndCall', 6], ['0', 7], ['1', 8], ['2', 9], ['3', 10], ['4', 11], ['5', 12], ['6', 13], ['7', 14], ['8', 15], ['9', 16], ['Star', 17], ['*', 17], ['Pound', 18], ['#', 18], ['DialUp', 19], ['DialDown', 20], ['DialLeft', 21], ['DialRight', 22], ['DialCenter', 23], ['VolumeUp', 24], ['VolumeDown', 25], ['Power', 26], ['Camera', 27], ['Clear', 28], ['A', 29], ['B', 30], ['C', 31], ['D', 32], ['E', 33], ['F', 34], ['G', 35], ['H', 36], ['I', 37], ['J', 38], ['K', 39], ['L', 40], ['M', 41], ['N', 42], ['O', 43], ['P', 44], ['Q', 45], ['R', 46], ['S', 47], ['T', 48], ['U', 49], ['V', 50], ['W', 51], ['X', 52], ['Y', 53], ['Z', 54], ['Comma', 55], [',', 55], ['Period', 56], ['.', 56], ['AltLeft', 57], ['AltRight', 58], ['ShiftLeft', 59], ['ShiftRight', 60], ['Tab', 61], ['\t', 61], ['Space', 62], [' ', 62], ['Sym', 63], ['Explorer', 64], ['Envelop', 65], ['Enter', 66], ['Del', 67], ['Grave', 68], ['Minus', 69], ['-', 69], ['Equals', 70], ['=', 70], ['LeftBracket', 71], ['(', 71], ['RightBracket', 72], [')', 72], ['Backslash', 73], ['\\', 73], ['Semicolon', 74], [';', 74], ['Apostrophe', 75], ['`', 75], ['Slash', 76], ['/', 76], ['At', 77], ['@', 77], ['Num', 78], ['HeadsetHook', 79], ['Focus', 80], ['Plus', 81], ['Menu', 82], ['Notification', 83], ['Search', 84], ['AppSwitch', 187], ['Assist', 219], ['Cut', 277], ['Copy', 278], ['Paste', 279]]);

View File

@@ -0,0 +1,118 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ArtifactDispatcher = void 0;
var _dispatcher = require("./dispatcher");
var _streamDispatcher = require("./streamDispatcher");
var _fs = _interopRequireDefault(require("fs"));
var _fileUtils = require("../../utils/fileUtils");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* 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 ArtifactDispatcher extends _dispatcher.Dispatcher {
static from(parentScope, artifact) {
return ArtifactDispatcher.fromNullable(parentScope, artifact);
}
static fromNullable(parentScope, artifact) {
if (!artifact) return undefined;
const result = (0, _dispatcher.existingDispatcher)(artifact);
return result || new ArtifactDispatcher(parentScope, artifact);
}
constructor(scope, artifact) {
super(scope, artifact, 'Artifact', {
absolutePath: artifact.localPath()
});
this._type_Artifact = true;
}
async pathAfterFinished() {
const path = await this._object.localPathAfterFinished();
return {
value: path || undefined
};
}
async saveAs(params) {
return await new Promise((resolve, reject) => {
this._object.saveAs(async (localPath, error) => {
if (error !== undefined) {
reject(new Error(error));
return;
}
try {
await (0, _fileUtils.mkdirIfNeeded)(params.path);
await _fs.default.promises.copyFile(localPath, params.path);
resolve();
} catch (e) {
reject(e);
}
});
});
}
async saveAsStream() {
return await new Promise((resolve, reject) => {
this._object.saveAs(async (localPath, error) => {
if (error !== undefined) {
reject(new Error(error));
return;
}
try {
const readable = _fs.default.createReadStream(localPath, {
highWaterMark: 1024 * 1024
});
const stream = new _streamDispatcher.StreamDispatcher(this, readable);
// Resolve with a stream, so that client starts saving the data.
resolve({
stream
});
// Block the Artifact until the stream is consumed.
await new Promise(resolve => {
readable.on('close', resolve);
readable.on('end', resolve);
readable.on('error', resolve);
});
} catch (e) {
reject(e);
}
});
});
}
async stream() {
const fileName = await this._object.localPathAfterFinished();
if (!fileName) return {};
const readable = _fs.default.createReadStream(fileName, {
highWaterMark: 1024 * 1024
});
return {
stream: new _streamDispatcher.StreamDispatcher(this, readable)
};
}
async failure() {
const error = await this._object.failureError();
return {
error: error || undefined
};
}
async cancel() {
await this._object.cancel();
}
async delete() {
await this._object.delete();
this._dispose();
}
}
exports.ArtifactDispatcher = ArtifactDispatcher;

View File

@@ -0,0 +1,290 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.BrowserContextDispatcher = void 0;
var _browserContext = require("../browserContext");
var _dispatcher = require("./dispatcher");
var _pageDispatcher = require("./pageDispatcher");
var _networkDispatchers = require("./networkDispatchers");
var _crBrowser = require("../chromium/crBrowser");
var _cdpSessionDispatcher = require("./cdpSessionDispatcher");
var _recorder = require("../recorder");
var _artifactDispatcher = require("./artifactDispatcher");
var _tracingDispatcher = require("./tracingDispatcher");
var fs = _interopRequireWildcard(require("fs"));
var path = _interopRequireWildcard(require("path"));
var _utils = require("../../utils");
var _writableStreamDispatcher = require("./writableStreamDispatcher");
var _consoleMessageDispatcher = require("./consoleMessageDispatcher");
var _dialogDispatcher = require("./dialogDispatcher");
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 (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 BrowserContextDispatcher extends _dispatcher.Dispatcher {
constructor(parentScope, context) {
// We will reparent these to the context below.
const requestContext = _networkDispatchers.APIRequestContextDispatcher.from(parentScope, context.fetchRequest);
const tracing = _tracingDispatcher.TracingDispatcher.from(parentScope, context.tracing);
super(parentScope, context, 'BrowserContext', {
isChromium: context._browser.options.isChromium,
requestContext,
tracing
});
this._type_EventTarget = true;
this._type_BrowserContext = true;
this._context = void 0;
this._subscriptions = new Set();
this.adopt(requestContext);
this.adopt(tracing);
this._context = context;
// Note: when launching persistent context, dispatcher is created very late,
// so we can already have pages, videos and everything else.
const onVideo = artifact => {
// Note: Video must outlive Page and BrowserContext, so that client can saveAs it
// after closing the context. We use |scope| for it.
const artifactDispatcher = _artifactDispatcher.ArtifactDispatcher.from(parentScope, artifact);
this._dispatchEvent('video', {
artifact: artifactDispatcher
});
};
this.addObjectListener(_browserContext.BrowserContext.Events.VideoStarted, onVideo);
for (const video of context._browser._idToVideo.values()) {
if (video.context === context) onVideo(video.artifact);
}
for (const page of context.pages()) this._dispatchEvent('page', {
page: _pageDispatcher.PageDispatcher.from(this, page)
});
this.addObjectListener(_browserContext.BrowserContext.Events.Page, page => {
this._dispatchEvent('page', {
page: _pageDispatcher.PageDispatcher.from(this, page)
});
});
this.addObjectListener(_browserContext.BrowserContext.Events.Close, () => {
this._dispatchEvent('close');
this._dispose();
});
this.addObjectListener(_browserContext.BrowserContext.Events.Console, message => {
if (this._shouldDispatchEvent(message.page(), 'console')) this._dispatchEvent('console', {
message: new _consoleMessageDispatcher.ConsoleMessageDispatcher(_pageDispatcher.PageDispatcher.from(this, message.page()), message)
});
});
this.addObjectListener(_browserContext.BrowserContext.Events.Dialog, dialog => {
if (this._shouldDispatchEvent(dialog.page(), 'dialog')) this._dispatchEvent('dialog', {
dialog: new _dialogDispatcher.DialogDispatcher(this, dialog)
});else dialog.close().catch(() => {});
});
if (context._browser.options.name === 'chromium') {
for (const page of context.backgroundPages()) this._dispatchEvent('backgroundPage', {
page: _pageDispatcher.PageDispatcher.from(this, page)
});
this.addObjectListener(_crBrowser.CRBrowserContext.CREvents.BackgroundPage, page => this._dispatchEvent('backgroundPage', {
page: _pageDispatcher.PageDispatcher.from(this, page)
}));
for (const serviceWorker of context.serviceWorkers()) this._dispatchEvent('serviceWorker', {
worker: new _pageDispatcher.WorkerDispatcher(this, serviceWorker)
});
this.addObjectListener(_crBrowser.CRBrowserContext.CREvents.ServiceWorker, serviceWorker => this._dispatchEvent('serviceWorker', {
worker: new _pageDispatcher.WorkerDispatcher(this, serviceWorker)
}));
}
this.addObjectListener(_browserContext.BrowserContext.Events.Request, request => {
var _request$frame;
// Create dispatcher, if:
// - There are listeners to the requests.
// - We are redirected from a reported request so that redirectedTo was updated on client.
// - We are a navigation request and dispatcher will be reported as a part of the goto return value and newDocument param anyways.
// By the time requestFinished is triggered to update the request, we should have a request on the client already.
const redirectFromDispatcher = request.redirectedFrom() && (0, _dispatcher.existingDispatcher)(request.redirectedFrom());
if (!redirectFromDispatcher && !this._shouldDispatchNetworkEvent(request, 'request') && !request.isNavigationRequest()) return;
const requestDispatcher = _networkDispatchers.RequestDispatcher.from(this, request);
this._dispatchEvent('request', {
request: requestDispatcher,
page: _pageDispatcher.PageDispatcher.fromNullable(this, (_request$frame = request.frame()) === null || _request$frame === void 0 ? void 0 : _request$frame._page.initializedOrUndefined())
});
});
this.addObjectListener(_browserContext.BrowserContext.Events.Response, response => {
var _response$frame;
const requestDispatcher = (0, _dispatcher.existingDispatcher)(response.request());
if (!requestDispatcher && !this._shouldDispatchNetworkEvent(response.request(), 'response')) return;
this._dispatchEvent('response', {
response: _networkDispatchers.ResponseDispatcher.from(this, response),
page: _pageDispatcher.PageDispatcher.fromNullable(this, (_response$frame = response.frame()) === null || _response$frame === void 0 ? void 0 : _response$frame._page.initializedOrUndefined())
});
});
this.addObjectListener(_browserContext.BrowserContext.Events.RequestFailed, request => {
var _request$frame2;
const requestDispatcher = (0, _dispatcher.existingDispatcher)(request);
if (!requestDispatcher && !this._shouldDispatchNetworkEvent(request, 'requestFailed')) return;
this._dispatchEvent('requestFailed', {
request: _networkDispatchers.RequestDispatcher.from(this, request),
failureText: request._failureText || undefined,
responseEndTiming: request._responseEndTiming,
page: _pageDispatcher.PageDispatcher.fromNullable(this, (_request$frame2 = request.frame()) === null || _request$frame2 === void 0 ? void 0 : _request$frame2._page.initializedOrUndefined())
});
});
this.addObjectListener(_browserContext.BrowserContext.Events.RequestFinished, ({
request,
response
}) => {
var _request$frame3;
const requestDispatcher = (0, _dispatcher.existingDispatcher)(request);
if (!requestDispatcher && !this._shouldDispatchNetworkEvent(request, 'requestFinished')) return;
this._dispatchEvent('requestFinished', {
request: _networkDispatchers.RequestDispatcher.from(this, request),
response: _networkDispatchers.ResponseDispatcher.fromNullable(this, response),
responseEndTiming: request._responseEndTiming,
page: _pageDispatcher.PageDispatcher.fromNullable(this, (_request$frame3 = request.frame()) === null || _request$frame3 === void 0 ? void 0 : _request$frame3._page.initializedOrUndefined())
});
});
}
_shouldDispatchNetworkEvent(request, event) {
var _request$frame4, _request$frame4$_page;
return this._shouldDispatchEvent((_request$frame4 = request.frame()) === null || _request$frame4 === void 0 ? void 0 : (_request$frame4$_page = _request$frame4._page) === null || _request$frame4$_page === void 0 ? void 0 : _request$frame4$_page.initializedOrUndefined(), event);
}
_shouldDispatchEvent(page, event) {
if (this._subscriptions.has(event)) return true;
const pageDispatcher = page ? (0, _dispatcher.existingDispatcher)(page) : undefined;
if (pageDispatcher !== null && pageDispatcher !== void 0 && pageDispatcher._subscriptions.has(event)) return true;
return false;
}
async createTempFile(params) {
const dir = this._context._browser.options.artifactsDir;
const tmpDir = path.join(dir, 'upload-' + (0, _utils.createGuid)());
await fs.promises.mkdir(tmpDir);
this._context._tempDirs.push(tmpDir);
const file = fs.createWriteStream(path.join(tmpDir, params.name));
return {
writableStream: new _writableStreamDispatcher.WritableStreamDispatcher(this, file)
};
}
async setDefaultNavigationTimeoutNoReply(params) {
this._context.setDefaultNavigationTimeout(params.timeout);
}
async setDefaultTimeoutNoReply(params) {
this._context.setDefaultTimeout(params.timeout);
}
async exposeBinding(params) {
await this._context.exposeBinding(params.name, !!params.needsHandle, (source, ...args) => {
// When reusing the context, we might have some bindings called late enough,
// after context and page dispatchers have been disposed.
if (this._disposed) return;
const pageDispatcher = _pageDispatcher.PageDispatcher.from(this, source.page);
const binding = new _pageDispatcher.BindingCallDispatcher(pageDispatcher, params.name, !!params.needsHandle, source, args);
this._dispatchEvent('bindingCall', {
binding
});
return binding.promise();
});
}
async newPage(params, metadata) {
return {
page: _pageDispatcher.PageDispatcher.from(this, await this._context.newPage(metadata))
};
}
async cookies(params) {
return {
cookies: await this._context.cookies(params.urls)
};
}
async addCookies(params) {
await this._context.addCookies(params.cookies);
}
async clearCookies() {
await this._context.clearCookies();
}
async grantPermissions(params) {
await this._context.grantPermissions(params.permissions, params.origin);
}
async clearPermissions() {
await this._context.clearPermissions();
}
async setGeolocation(params) {
await this._context.setGeolocation(params.geolocation);
}
async setExtraHTTPHeaders(params) {
await this._context.setExtraHTTPHeaders(params.headers);
}
async setOffline(params) {
await this._context.setOffline(params.offline);
}
async setHTTPCredentials(params) {
await this._context.setHTTPCredentials(params.httpCredentials);
}
async addInitScript(params) {
await this._context.addInitScript(params.source);
}
async setNetworkInterceptionPatterns(params) {
if (!params.patterns.length) {
await this._context.setRequestInterceptor(undefined);
return;
}
const urlMatchers = params.patterns.map(pattern => pattern.regexSource ? new RegExp(pattern.regexSource, pattern.regexFlags) : pattern.glob);
await this._context.setRequestInterceptor((route, request) => {
const matchesSome = urlMatchers.some(urlMatch => (0, _utils.urlMatches)(this._context._options.baseURL, request.url(), urlMatch));
if (!matchesSome) return false;
this._dispatchEvent('route', {
route: _networkDispatchers.RouteDispatcher.from(_networkDispatchers.RequestDispatcher.from(this, request), route)
});
return true;
});
}
async storageState(params, metadata) {
return await this._context.storageState();
}
async close(params, metadata) {
await this._context.close(metadata);
}
async recorderSupplementEnable(params) {
await _recorder.Recorder.show(this._context, params);
}
async pause(params, metadata) {
// Debugger will take care of this.
}
async newCDPSession(params) {
if (!this._object._browser.options.isChromium) throw new Error(`CDP session is only available in Chromium`);
if (!params.page && !params.frame || params.page && params.frame) throw new Error(`CDP session must be initiated with either Page or Frame, not none or both`);
const crBrowserContext = this._object;
return {
session: new _cdpSessionDispatcher.CDPSessionDispatcher(this, await crBrowserContext.newCDPSession((params.page ? params.page : params.frame)._object))
};
}
async harStart(params) {
const harId = await this._context._harStart(params.page ? params.page._object : null, params.options);
return {
harId
};
}
async harExport(params) {
const artifact = await this._context._harExport(params.harId);
if (!artifact) throw new Error('No HAR artifact. Ensure record.harPath is set.');
return {
artifact: _artifactDispatcher.ArtifactDispatcher.from(this, artifact)
};
}
async updateSubscription(params) {
if (params.enabled) this._subscriptions.add(params.event);else this._subscriptions.delete(params.event);
}
_onDispose() {
// Avoid protocol calls for the closed context.
if (!this._context.isClosingOrClosed()) this._context.setRequestInterceptor(undefined).catch(() => {});
}
}
exports.BrowserContextDispatcher = BrowserContextDispatcher;

View File

@@ -0,0 +1,160 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ConnectedBrowserDispatcher = exports.BrowserDispatcher = void 0;
var _browser = require("../browser");
var _browserContextDispatcher = require("./browserContextDispatcher");
var _cdpSessionDispatcher = require("./cdpSessionDispatcher");
var _dispatcher = require("./dispatcher");
var _instrumentation = require("../instrumentation");
var _browserContext = require("../browserContext");
var _selectors = require("../selectors");
/**
* 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 BrowserDispatcher extends _dispatcher.Dispatcher {
constructor(scope, browser) {
super(scope, browser, 'Browser', {
version: browser.version(),
name: browser.options.name
});
this._type_Browser = true;
this.addObjectListener(_browser.Browser.Events.Disconnected, () => this._didClose());
}
_didClose() {
this._dispatchEvent('close');
this._dispose();
}
async newContext(params, metadata) {
const context = await this._object.newContext(metadata, params);
return {
context: new _browserContextDispatcher.BrowserContextDispatcher(this, context)
};
}
async newContextForReuse(params, metadata) {
return await newContextForReuse(this._object, this, params, null, metadata);
}
async close() {
await this._object.close();
}
async killForTests() {
await this._object.killForTests();
}
async defaultUserAgentForTest() {
return {
userAgent: this._object.userAgent()
};
}
async newBrowserCDPSession() {
if (!this._object.options.isChromium) throw new Error(`CDP session is only available in Chromium`);
const crBrowser = this._object;
return {
session: new _cdpSessionDispatcher.CDPSessionDispatcher(this, await crBrowser.newBrowserCDPSession())
};
}
async startTracing(params) {
if (!this._object.options.isChromium) throw new Error(`Tracing is only available in Chromium`);
const crBrowser = this._object;
await crBrowser.startTracing(params.page ? params.page._object : undefined, params);
}
async stopTracing() {
if (!this._object.options.isChromium) throw new Error(`Tracing is only available in Chromium`);
const crBrowser = this._object;
return {
binary: await crBrowser.stopTracing()
};
}
}
// This class implements multiplexing browser dispatchers over a single Browser instance.
exports.BrowserDispatcher = BrowserDispatcher;
class ConnectedBrowserDispatcher extends _dispatcher.Dispatcher {
constructor(scope, browser) {
super(scope, browser, 'Browser', {
version: browser.version(),
name: browser.options.name
});
// When we have a remotely-connected browser, each client gets a fresh Selector instance,
// so that two clients do not interfere between each other.
this._type_Browser = true;
this._contexts = new Set();
this.selectors = void 0;
this.selectors = new _selectors.Selectors();
}
async newContext(params, metadata) {
if (params.recordVideo) params.recordVideo.dir = this._object.options.artifactsDir;
const context = await this._object.newContext(metadata, params);
this._contexts.add(context);
context.setSelectors(this.selectors);
context.on(_browserContext.BrowserContext.Events.Close, () => this._contexts.delete(context));
return {
context: new _browserContextDispatcher.BrowserContextDispatcher(this, context)
};
}
async newContextForReuse(params, metadata) {
return await newContextForReuse(this._object, this, params, this.selectors, metadata);
}
async close() {
// Client should not send us Browser.close.
}
async killForTests() {
// Client should not send us Browser.killForTests.
}
async defaultUserAgentForTest() {
throw new Error('Client should not send us Browser.defaultUserAgentForTest');
}
async newBrowserCDPSession() {
if (!this._object.options.isChromium) throw new Error(`CDP session is only available in Chromium`);
const crBrowser = this._object;
return {
session: new _cdpSessionDispatcher.CDPSessionDispatcher(this, await crBrowser.newBrowserCDPSession())
};
}
async startTracing(params) {
if (!this._object.options.isChromium) throw new Error(`Tracing is only available in Chromium`);
const crBrowser = this._object;
await crBrowser.startTracing(params.page ? params.page._object : undefined, params);
}
async stopTracing() {
if (!this._object.options.isChromium) throw new Error(`Tracing is only available in Chromium`);
const crBrowser = this._object;
return {
binary: await crBrowser.stopTracing()
};
}
async cleanupContexts() {
await Promise.all(Array.from(this._contexts).map(context => context.close((0, _instrumentation.serverSideCallMetadata)())));
}
}
exports.ConnectedBrowserDispatcher = ConnectedBrowserDispatcher;
async function newContextForReuse(browser, scope, params, selectors, metadata) {
const {
context,
needsReset
} = await browser.newContextForReuse(params, metadata);
if (needsReset) {
const oldContextDispatcher = (0, _dispatcher.existingDispatcher)(context);
if (oldContextDispatcher) oldContextDispatcher._dispose();
await context.resetForReuse(metadata, params);
}
if (selectors) context.setSelectors(selectors);
const contextDispatcher = new _browserContextDispatcher.BrowserContextDispatcher(scope, context);
return {
context: contextDispatcher
};
}

View File

@@ -0,0 +1,55 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.BrowserTypeDispatcher = void 0;
var _browserDispatcher = require("./browserDispatcher");
var _dispatcher = require("./dispatcher");
var _browserContextDispatcher = require("./browserContextDispatcher");
/**
* 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 BrowserTypeDispatcher extends _dispatcher.Dispatcher {
constructor(scope, browserType) {
super(scope, browserType, 'BrowserType', {
executablePath: browserType.executablePath(),
name: browserType.name()
});
this._type_BrowserType = true;
}
async launch(params, metadata) {
const browser = await this._object.launch(metadata, params);
return {
browser: new _browserDispatcher.BrowserDispatcher(this, browser)
};
}
async launchPersistentContext(params, metadata) {
const browserContext = await this._object.launchPersistentContext(metadata, params.userDataDir, params);
return {
context: new _browserContextDispatcher.BrowserContextDispatcher(this, browserContext)
};
}
async connectOverCDP(params, metadata) {
const browser = await this._object.connectOverCDP(metadata, params.endpointURL, params, params.timeout);
const browserDispatcher = new _browserDispatcher.BrowserDispatcher(this, browser);
return {
browser: browserDispatcher,
defaultContext: browser._defaultContext ? new _browserContextDispatcher.BrowserContextDispatcher(browserDispatcher, browser._defaultContext) : undefined
};
}
}
exports.BrowserTypeDispatcher = BrowserTypeDispatcher;

View File

@@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.CDPSessionDispatcher = void 0;
var _crConnection = require("../chromium/crConnection");
var _dispatcher = require("./dispatcher");
/**
* 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 CDPSessionDispatcher extends _dispatcher.Dispatcher {
constructor(scope, crSession) {
super(scope, crSession, 'CDPSession', {});
this._type_CDPSession = true;
crSession._eventListener = (method, params) => {
this._dispatchEvent('event', {
method,
params
});
};
this.addObjectListener(_crConnection.CRSessionEvents.Disconnected, () => this._dispose());
}
async send(params) {
return {
result: await this._object.send(params.method, params.params)
};
}
async detach() {
return this._object.detach();
}
}
exports.CDPSessionDispatcher = CDPSessionDispatcher;

View File

@@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ConsoleMessageDispatcher = void 0;
var _dispatcher = require("./dispatcher");
var _elementHandlerDispatcher = require("./elementHandlerDispatcher");
/**
* 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 ConsoleMessageDispatcher extends _dispatcher.Dispatcher {
constructor(page, message) {
super(page, message, 'ConsoleMessage', {
type: message.type(),
text: message.text(),
args: message.args().map(a => _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(page, a)),
location: message.location(),
page
});
this._type_ConsoleMessage = true;
}
}
exports.ConsoleMessageDispatcher = ConsoleMessageDispatcher;

View File

@@ -0,0 +1,97 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.DebugControllerDispatcher = void 0;
var _utils = require("playwright-core/lib/utils");
var _debugController = require("../debugController");
var _dispatcher = require("./dispatcher");
/**
* 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 DebugControllerDispatcher extends _dispatcher.Dispatcher {
constructor(connection, debugController) {
super(connection, debugController, 'DebugController', {});
this._type_DebugController = void 0;
this._listeners = void 0;
this._type_DebugController = true;
this._listeners = [_utils.eventsHelper.addEventListener(this._object, _debugController.DebugController.Events.StateChanged, params => {
this._dispatchEvent('stateChanged', params);
}), _utils.eventsHelper.addEventListener(this._object, _debugController.DebugController.Events.InspectRequested, ({
selector,
locator
}) => {
this._dispatchEvent('inspectRequested', {
selector,
locator
});
}), _utils.eventsHelper.addEventListener(this._object, _debugController.DebugController.Events.SourceChanged, ({
text,
header,
footer,
actions
}) => {
this._dispatchEvent('sourceChanged', {
text,
header,
footer,
actions
});
}), _utils.eventsHelper.addEventListener(this._object, _debugController.DebugController.Events.Paused, ({
paused
}) => {
this._dispatchEvent('paused', {
paused
});
})];
}
async initialize(params) {
this._object.initialize(params.codegenId, params.sdkLanguage);
}
async setReportStateChanged(params) {
this._object.setReportStateChanged(params.enabled);
}
async resetForReuse() {
await this._object.resetForReuse();
}
async navigate(params) {
await this._object.navigate(params.url);
}
async setRecorderMode(params) {
await this._object.setRecorderMode(params);
}
async highlight(params) {
await this._object.highlight(params.selector);
}
async hideHighlight() {
await this._object.hideHighlight();
}
async resume() {
await this._object.resume();
}
async kill() {
await this._object.kill();
}
async closeAllBrowsers() {
await this._object.closeAllBrowsers();
}
_onDispose() {
_utils.eventsHelper.removeEventListeners(this._listeners);
this._object.dispose();
}
}
exports.DebugControllerDispatcher = DebugControllerDispatcher;

View File

@@ -0,0 +1,44 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.DialogDispatcher = void 0;
var _dispatcher = require("./dispatcher");
var _pageDispatcher = require("./pageDispatcher");
/**
* 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 DialogDispatcher extends _dispatcher.Dispatcher {
constructor(scope, dialog) {
const page = _pageDispatcher.PageDispatcher.fromNullable(scope, dialog.page().initializedOrUndefined());
// Prefer scoping to the page, unless we don't have one.
super(page || scope, dialog, 'Dialog', {
page,
type: dialog.type(),
message: dialog.message(),
defaultValue: dialog.defaultValue()
});
this._type_Dialog = true;
}
async accept(params) {
await this._object.accept(params.promptText);
}
async dismiss() {
await this._object.dismiss();
}
}
exports.DialogDispatcher = DialogDispatcher;

View File

@@ -0,0 +1,344 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.dispatcherSymbol = exports.RootDispatcher = exports.DispatcherConnection = exports.Dispatcher = void 0;
exports.existingDispatcher = existingDispatcher;
var _events = require("events");
var _serializers = require("../../protocol/serializers");
var _validator = require("../../protocol/validator");
var _utils = require("../../utils");
var _errors = require("../../common/errors");
var _instrumentation = require("../instrumentation");
var _stackTrace = require("../../utils/stackTrace");
var _eventsHelper = require("../..//utils/eventsHelper");
/**
* 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 dispatcherSymbol = Symbol('dispatcher');
exports.dispatcherSymbol = dispatcherSymbol;
const metadataValidator = (0, _validator.createMetadataValidator)();
function existingDispatcher(object) {
return object[dispatcherSymbol];
}
class Dispatcher extends _events.EventEmitter {
// Parent is always "isScope".
// Only "isScope" channel owners have registered dispatchers inside.
constructor(parent, object, type, initializer) {
super();
this._connection = void 0;
this._parent = void 0;
this._dispatchers = new Map();
this._disposed = false;
this._eventListeners = [];
this._guid = void 0;
this._type = void 0;
this._object = void 0;
this._connection = parent instanceof DispatcherConnection ? parent : parent._connection;
this._parent = parent instanceof DispatcherConnection ? undefined : parent;
const guid = object.guid;
(0, _utils.assert)(!this._connection._dispatchers.has(guid));
this._connection._dispatchers.set(guid, this);
if (this._parent) {
(0, _utils.assert)(!this._parent._dispatchers.has(guid));
this._parent._dispatchers.set(guid, this);
}
this._type = type;
this._guid = guid;
this._object = object;
object[dispatcherSymbol] = this;
if (this._parent) this._connection.sendCreate(this._parent, type, guid, initializer, this._parent._object);
}
parentScope() {
return this._parent;
}
addObjectListener(eventName, handler) {
this._eventListeners.push(_eventsHelper.eventsHelper.addEventListener(this._object, eventName, handler));
}
adopt(child) {
const oldParent = child._parent;
oldParent._dispatchers.delete(child._guid);
this._dispatchers.set(child._guid, child);
child._parent = this;
this._connection.sendAdopt(this, child);
}
_dispatchEvent(method, params) {
if (this._disposed) {
if ((0, _utils.isUnderTest)()) throw new Error(`${this._guid} is sending "${String(method)}" event after being disposed`);
// Just ignore this event outside of tests.
return;
}
const sdkObject = this._object instanceof _instrumentation.SdkObject ? this._object : undefined;
this._connection.sendEvent(this, method, params, sdkObject);
}
_dispose() {
this._disposeRecursively();
this._connection.sendDispose(this);
}
_onDispose() {}
_disposeRecursively() {
(0, _utils.assert)(!this._disposed, `${this._guid} is disposed more than once`);
this._onDispose();
this._disposed = true;
_eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
// Clean up from parent and connection.
if (this._parent) this._parent._dispatchers.delete(this._guid);
this._connection._dispatchers.delete(this._guid);
// Dispose all children.
for (const dispatcher of [...this._dispatchers.values()]) dispatcher._disposeRecursively();
this._dispatchers.clear();
delete this._object[dispatcherSymbol];
}
_debugScopeState() {
return {
_guid: this._guid,
objects: Array.from(this._dispatchers.values()).map(o => o._debugScopeState())
};
}
async waitForEventInfo() {
// Instrumentation takes care of this.
}
}
exports.Dispatcher = Dispatcher;
class RootDispatcher extends Dispatcher {
constructor(connection, createPlaywright) {
super(connection, {
guid: ''
}, 'Root', {});
this._initialized = false;
this.createPlaywright = createPlaywright;
}
async initialize(params) {
(0, _utils.assert)(this.createPlaywright);
(0, _utils.assert)(!this._initialized);
this._initialized = true;
return {
playwright: await this.createPlaywright(this, params)
};
}
}
exports.RootDispatcher = RootDispatcher;
class DispatcherConnection {
constructor(isLocal) {
this._dispatchers = new Map();
this.onmessage = message => {};
this._waitOperations = new Map();
this._isLocal = void 0;
this._isLocal = !!isLocal;
}
sendEvent(dispatcher, event, params, sdkObject) {
const validator = (0, _validator.findValidator)(dispatcher._type, event, 'Event');
params = validator(params, '', {
tChannelImpl: this._tChannelImplToWire.bind(this),
binary: this._isLocal ? 'buffer' : 'toBase64'
});
this._sendMessageToClient(dispatcher._guid, dispatcher._type, event, params, sdkObject);
}
sendCreate(parent, type, guid, initializer, sdkObject) {
const validator = (0, _validator.findValidator)(type, '', 'Initializer');
initializer = validator(initializer, '', {
tChannelImpl: this._tChannelImplToWire.bind(this),
binary: this._isLocal ? 'buffer' : 'toBase64'
});
this._sendMessageToClient(parent._guid, type, '__create__', {
type,
initializer,
guid
}, sdkObject);
}
sendAdopt(parent, dispatcher) {
this._sendMessageToClient(parent._guid, dispatcher._type, '__adopt__', {
guid: dispatcher._guid
});
}
sendDispose(dispatcher) {
this._sendMessageToClient(dispatcher._guid, dispatcher._type, '__dispose__', {});
}
_sendMessageToClient(guid, type, method, params, sdkObject) {
if (sdkObject) {
var _sdkObject$attributio, _sdkObject$attributio2, _sdkObject$instrument;
const event = {
type: 'event',
class: type,
method,
params: params || {},
time: (0, _utils.monotonicTime)(),
pageId: sdkObject === null || sdkObject === void 0 ? void 0 : (_sdkObject$attributio = sdkObject.attribution) === null || _sdkObject$attributio === void 0 ? void 0 : (_sdkObject$attributio2 = _sdkObject$attributio.page) === null || _sdkObject$attributio2 === void 0 ? void 0 : _sdkObject$attributio2.guid
};
(_sdkObject$instrument = sdkObject.instrumentation) === null || _sdkObject$instrument === void 0 ? void 0 : _sdkObject$instrument.onEvent(sdkObject, event);
}
this.onmessage({
guid,
method,
params
});
}
_tChannelImplFromWire(names, arg, path, context) {
if (arg && typeof arg === 'object' && typeof arg.guid === 'string') {
const guid = arg.guid;
const dispatcher = this._dispatchers.get(guid);
if (!dispatcher) throw new _validator.ValidationError(`${path}: no object with guid ${guid}`);
if (names !== '*' && !names.includes(dispatcher._type)) throw new _validator.ValidationError(`${path}: object with guid ${guid} has type ${dispatcher._type}, expected ${names.toString()}`);
return dispatcher;
}
throw new _validator.ValidationError(`${path}: expected guid for ${names.toString()}`);
}
_tChannelImplToWire(names, arg, path, context) {
if (arg instanceof Dispatcher) {
if (names !== '*' && !names.includes(arg._type)) throw new _validator.ValidationError(`${path}: dispatcher with guid ${arg._guid} has type ${arg._type}, expected ${names.toString()}`);
return {
guid: arg._guid
};
}
throw new _validator.ValidationError(`${path}: expected dispatcher ${names.toString()}`);
}
async dispatch(message) {
var _sdkObject$attributio3, _sdkObject$attributio4, _sdkObject$attributio5, _sdkObject$attributio6, _params$info;
const {
id,
guid,
method,
params,
metadata
} = message;
const dispatcher = this._dispatchers.get(guid);
if (!dispatcher) {
this.onmessage({
id,
error: (0, _serializers.serializeError)(new Error(_errors.kBrowserOrContextClosedError))
});
return;
}
let validParams;
let validMetadata;
try {
const validator = (0, _validator.findValidator)(dispatcher._type, method, 'Params');
validParams = validator(params, '', {
tChannelImpl: this._tChannelImplFromWire.bind(this),
binary: this._isLocal ? 'buffer' : 'fromBase64'
});
validMetadata = metadataValidator(metadata, '', {
tChannelImpl: this._tChannelImplFromWire.bind(this),
binary: this._isLocal ? 'buffer' : 'fromBase64'
});
if (typeof dispatcher[method] !== 'function') throw new Error(`Mismatching dispatcher: "${dispatcher._type}" does not implement "${method}"`);
} catch (e) {
this.onmessage({
id,
error: (0, _serializers.serializeError)(e)
});
return;
}
const sdkObject = dispatcher._object instanceof _instrumentation.SdkObject ? dispatcher._object : undefined;
const callMetadata = {
id: `call@${id}`,
wallTime: validMetadata.wallTime || Date.now(),
location: validMetadata.location,
apiName: validMetadata.apiName,
internal: validMetadata.internal,
objectId: sdkObject === null || sdkObject === void 0 ? void 0 : sdkObject.guid,
pageId: sdkObject === null || sdkObject === void 0 ? void 0 : (_sdkObject$attributio3 = sdkObject.attribution) === null || _sdkObject$attributio3 === void 0 ? void 0 : (_sdkObject$attributio4 = _sdkObject$attributio3.page) === null || _sdkObject$attributio4 === void 0 ? void 0 : _sdkObject$attributio4.guid,
frameId: sdkObject === null || sdkObject === void 0 ? void 0 : (_sdkObject$attributio5 = sdkObject.attribution) === null || _sdkObject$attributio5 === void 0 ? void 0 : (_sdkObject$attributio6 = _sdkObject$attributio5.frame) === null || _sdkObject$attributio6 === void 0 ? void 0 : _sdkObject$attributio6.guid,
startTime: (0, _utils.monotonicTime)(),
endTime: 0,
type: dispatcher._type,
method,
params: params || {},
log: []
};
if (sdkObject && params !== null && params !== void 0 && (_params$info = params.info) !== null && _params$info !== void 0 && _params$info.waitId) {
// Process logs for waitForNavigation/waitForLoadState/etc.
const info = params.info;
switch (info.phase) {
case 'before':
{
this._waitOperations.set(info.waitId, callMetadata);
await sdkObject.instrumentation.onBeforeCall(sdkObject, callMetadata);
this.onmessage({
id
});
return;
}
case 'log':
{
const originalMetadata = this._waitOperations.get(info.waitId);
originalMetadata.log.push(info.message);
sdkObject.instrumentation.onCallLog(sdkObject, originalMetadata, 'api', info.message);
this.onmessage({
id
});
return;
}
case 'after':
{
const originalMetadata = this._waitOperations.get(info.waitId);
originalMetadata.endTime = (0, _utils.monotonicTime)();
originalMetadata.error = info.error ? {
error: {
name: 'Error',
message: info.error
}
} : undefined;
this._waitOperations.delete(info.waitId);
await sdkObject.instrumentation.onAfterCall(sdkObject, originalMetadata);
this.onmessage({
id
});
return;
}
}
}
let error;
await (sdkObject === null || sdkObject === void 0 ? void 0 : sdkObject.instrumentation.onBeforeCall(sdkObject, callMetadata));
try {
const result = await dispatcher[method](validParams, callMetadata);
const validator = (0, _validator.findValidator)(dispatcher._type, method, 'Result');
callMetadata.result = validator(result, '', {
tChannelImpl: this._tChannelImplToWire.bind(this),
binary: this._isLocal ? 'buffer' : 'toBase64'
});
} catch (e) {
// Dispatching error
// We want original, unmodified error in metadata.
callMetadata.error = (0, _serializers.serializeError)(e);
if (callMetadata.log.length) (0, _stackTrace.rewriteErrorMessage)(e, e.message + formatLogRecording(callMetadata.log));
error = (0, _serializers.serializeError)(e);
} finally {
callMetadata.endTime = (0, _utils.monotonicTime)();
await (sdkObject === null || sdkObject === void 0 ? void 0 : sdkObject.instrumentation.onAfterCall(sdkObject, callMetadata));
}
const response = {
id
};
if (callMetadata.result) response.result = callMetadata.result;
if (error) response.error = error;
this.onmessage(response);
}
}
exports.DispatcherConnection = DispatcherConnection;
function formatLogRecording(log) {
if (!log.length) return '';
const header = ` logs `;
const headerLength = 60;
const leftLength = (headerLength - header.length) / 2;
const rightLength = headerLength - header.length - leftLength;
return `\n${'='.repeat(leftLength)}${header}${'='.repeat(rightLength)}\n${log.join('\n')}\n${'='.repeat(headerLength)}`;
}

View File

@@ -0,0 +1,80 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ElectronDispatcher = exports.ElectronApplicationDispatcher = void 0;
var _dispatcher = require("./dispatcher");
var _electron = require("../electron/electron");
var _browserContextDispatcher = require("./browserContextDispatcher");
var _jsHandleDispatcher = require("./jsHandleDispatcher");
var _elementHandlerDispatcher = require("./elementHandlerDispatcher");
/**
* 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 ElectronDispatcher extends _dispatcher.Dispatcher {
constructor(scope, electron) {
super(scope, electron, 'Electron', {});
this._type_Electron = true;
}
async launch(params) {
const electronApplication = await this._object.launch(params);
return {
electronApplication: new ElectronApplicationDispatcher(this, electronApplication)
};
}
}
exports.ElectronDispatcher = ElectronDispatcher;
class ElectronApplicationDispatcher extends _dispatcher.Dispatcher {
constructor(scope, electronApplication) {
super(scope, electronApplication, 'ElectronApplication', {
context: new _browserContextDispatcher.BrowserContextDispatcher(scope, electronApplication.context())
});
this._type_EventTarget = true;
this._type_ElectronApplication = true;
this.addObjectListener(_electron.ElectronApplication.Events.Close, () => {
this._dispatchEvent('close');
this._dispose();
});
}
async browserWindow(params) {
const handle = await this._object.browserWindow(params.page.page());
return {
handle: _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(this, handle)
};
}
async evaluateExpression(params) {
const handle = await this._object._nodeElectronHandlePromise;
return {
value: (0, _jsHandleDispatcher.serializeResult)(await handle.evaluateExpression(params.expression, {
isFunction: params.isFunction
}, (0, _jsHandleDispatcher.parseArgument)(params.arg)))
};
}
async evaluateExpressionHandle(params) {
const handle = await this._object._nodeElectronHandlePromise;
const result = await handle.evaluateExpressionHandle(params.expression, {
isFunction: params.isFunction
}, (0, _jsHandleDispatcher.parseArgument)(params.arg));
return {
handle: _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(this, result)
};
}
async close() {
await this._object.close();
}
}
exports.ElectronApplicationDispatcher = ElectronApplicationDispatcher;

View File

@@ -0,0 +1,233 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ElementHandleDispatcher = void 0;
var _dispatcher = require("./dispatcher");
var _jsHandleDispatcher = require("./jsHandleDispatcher");
var _frameDispatcher = require("./frameDispatcher");
var _utils = require("../../utils");
var _path = _interopRequireDefault(require("path"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* 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 ElementHandleDispatcher extends _jsHandleDispatcher.JSHandleDispatcher {
static from(scope, handle) {
return (0, _dispatcher.existingDispatcher)(handle) || new ElementHandleDispatcher(scope, handle);
}
static fromNullable(scope, handle) {
if (!handle) return undefined;
return (0, _dispatcher.existingDispatcher)(handle) || new ElementHandleDispatcher(scope, handle);
}
static fromJSHandle(scope, handle) {
const result = (0, _dispatcher.existingDispatcher)(handle);
if (result) return result;
return handle.asElement() ? new ElementHandleDispatcher(scope, handle.asElement()) : new _jsHandleDispatcher.JSHandleDispatcher(scope, handle);
}
constructor(scope, elementHandle) {
super(scope, elementHandle);
this._type_ElementHandle = true;
this._elementHandle = void 0;
this._elementHandle = elementHandle;
}
async ownerFrame(params, metadata) {
const frame = await this._elementHandle.ownerFrame();
return {
frame: frame ? _frameDispatcher.FrameDispatcher.from(this.parentScope(), frame) : undefined
};
}
async contentFrame(params, metadata) {
const frame = await this._elementHandle.contentFrame();
return {
frame: frame ? _frameDispatcher.FrameDispatcher.from(this.parentScope(), frame) : undefined
};
}
async getAttribute(params, metadata) {
const value = await this._elementHandle.getAttribute(params.name);
return {
value: value === null ? undefined : value
};
}
async inputValue(params, metadata) {
const value = await this._elementHandle.inputValue();
return {
value
};
}
async textContent(params, metadata) {
const value = await this._elementHandle.textContent();
return {
value: value === null ? undefined : value
};
}
async innerText(params, metadata) {
return {
value: await this._elementHandle.innerText()
};
}
async innerHTML(params, metadata) {
return {
value: await this._elementHandle.innerHTML()
};
}
async isChecked(params, metadata) {
return {
value: await this._elementHandle.isChecked()
};
}
async isDisabled(params, metadata) {
return {
value: await this._elementHandle.isDisabled()
};
}
async isEditable(params, metadata) {
return {
value: await this._elementHandle.isEditable()
};
}
async isEnabled(params, metadata) {
return {
value: await this._elementHandle.isEnabled()
};
}
async isHidden(params, metadata) {
return {
value: await this._elementHandle.isHidden()
};
}
async isVisible(params, metadata) {
return {
value: await this._elementHandle.isVisible()
};
}
async dispatchEvent(params, metadata) {
await this._elementHandle.dispatchEvent(params.type, (0, _jsHandleDispatcher.parseArgument)(params.eventInit));
}
async scrollIntoViewIfNeeded(params, metadata) {
await this._elementHandle.scrollIntoViewIfNeeded(metadata, params);
}
async hover(params, metadata) {
return await this._elementHandle.hover(metadata, params);
}
async click(params, metadata) {
return await this._elementHandle.click(metadata, params);
}
async dblclick(params, metadata) {
return await this._elementHandle.dblclick(metadata, params);
}
async tap(params, metadata) {
return await this._elementHandle.tap(metadata, params);
}
async selectOption(params, metadata) {
const elements = (params.elements || []).map(e => e._elementHandle);
return {
values: await this._elementHandle.selectOption(metadata, elements, params.options || [], params)
};
}
async fill(params, metadata) {
return await this._elementHandle.fill(metadata, params.value, params);
}
async selectText(params, metadata) {
await this._elementHandle.selectText(metadata, params);
}
async setInputFiles(params, metadata) {
return await this._elementHandle.setInputFiles(metadata, {
files: params.files
}, params);
}
async setInputFilePaths(params, metadata) {
let {
localPaths
} = params;
if (!localPaths) {
if (!params.streams) throw new Error('Neither localPaths nor streams is specified');
localPaths = params.streams.map(c => c.path());
}
for (const p of localPaths) (0, _utils.assert)(_path.default.isAbsolute(p) && _path.default.resolve(p) === p, 'Paths provided to localPaths must be absolute and fully resolved.');
return await this._elementHandle.setInputFiles(metadata, {
localPaths
}, params);
}
async focus(params, metadata) {
await this._elementHandle.focus(metadata);
}
async type(params, metadata) {
return await this._elementHandle.type(metadata, params.text, params);
}
async press(params, metadata) {
return await this._elementHandle.press(metadata, params.key, params);
}
async check(params, metadata) {
return await this._elementHandle.check(metadata, params);
}
async uncheck(params, metadata) {
return await this._elementHandle.uncheck(metadata, params);
}
async boundingBox(params, metadata) {
const value = await this._elementHandle.boundingBox();
return {
value: value || undefined
};
}
async screenshot(params, metadata) {
const mask = (params.mask || []).map(({
frame,
selector
}) => ({
frame: frame._object,
selector
}));
return {
binary: await this._elementHandle.screenshot(metadata, {
...params,
mask
})
};
}
async querySelector(params, metadata) {
const handle = await this._elementHandle.querySelector(params.selector, params);
return {
element: ElementHandleDispatcher.fromNullable(this.parentScope(), handle)
};
}
async querySelectorAll(params, metadata) {
const elements = await this._elementHandle.querySelectorAll(params.selector);
return {
elements: elements.map(e => ElementHandleDispatcher.from(this.parentScope(), e))
};
}
async evalOnSelector(params, metadata) {
return {
value: (0, _jsHandleDispatcher.serializeResult)(await this._elementHandle.evalOnSelector(params.selector, !!params.strict, params.expression, params.isFunction, (0, _jsHandleDispatcher.parseArgument)(params.arg)))
};
}
async evalOnSelectorAll(params, metadata) {
return {
value: (0, _jsHandleDispatcher.serializeResult)(await this._elementHandle.evalOnSelectorAll(params.selector, params.expression, params.isFunction, (0, _jsHandleDispatcher.parseArgument)(params.arg)))
};
}
async waitForElementState(params, metadata) {
await this._elementHandle.waitForElementState(metadata, params.state, params);
}
async waitForSelector(params, metadata) {
return {
element: ElementHandleDispatcher.fromNullable(this.parentScope(), await this._elementHandle.waitForSelector(metadata, params.selector, params))
};
}
}
exports.ElementHandleDispatcher = ElementHandleDispatcher;

View File

@@ -0,0 +1,300 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.FrameDispatcher = void 0;
var _frames = require("../frames");
var _dispatcher = require("./dispatcher");
var _elementHandlerDispatcher = require("./elementHandlerDispatcher");
var _jsHandleDispatcher = require("./jsHandleDispatcher");
var _networkDispatchers = require("./networkDispatchers");
var _utils = require("../../utils");
var _path = _interopRequireDefault(require("path"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* 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 FrameDispatcher extends _dispatcher.Dispatcher {
static from(scope, frame) {
const result = (0, _dispatcher.existingDispatcher)(frame);
return result || new FrameDispatcher(scope, frame);
}
static fromNullable(scope, frame) {
if (!frame) return;
return FrameDispatcher.from(scope, frame);
}
constructor(scope, frame) {
super(scope, frame, 'Frame', {
url: frame.url(),
name: frame.name(),
parentFrame: FrameDispatcher.fromNullable(scope, frame.parentFrame()),
loadStates: Array.from(frame._firedLifecycleEvents)
});
this._type_Frame = true;
this._frame = void 0;
this._frame = frame;
this.addObjectListener(_frames.Frame.Events.AddLifecycle, lifecycleEvent => {
this._dispatchEvent('loadstate', {
add: lifecycleEvent
});
});
this.addObjectListener(_frames.Frame.Events.RemoveLifecycle, lifecycleEvent => {
this._dispatchEvent('loadstate', {
remove: lifecycleEvent
});
});
this.addObjectListener(_frames.Frame.Events.InternalNavigation, event => {
if (!event.isPublic) return;
const params = {
url: event.url,
name: event.name,
error: event.error ? event.error.message : undefined
};
if (event.newDocument) params.newDocument = {
request: _networkDispatchers.RequestDispatcher.fromNullable(this.parentScope().parentScope(), event.newDocument.request || null)
};
this._dispatchEvent('navigated', params);
});
}
async goto(params, metadata) {
return {
response: _networkDispatchers.ResponseDispatcher.fromNullable(this.parentScope().parentScope(), await this._frame.goto(metadata, params.url, params))
};
}
async frameElement() {
return {
element: _elementHandlerDispatcher.ElementHandleDispatcher.from(this.parentScope(), await this._frame.frameElement())
};
}
async evaluateExpression(params, metadata) {
return {
value: (0, _jsHandleDispatcher.serializeResult)(await this._frame.evaluateExpression(params.expression, {
isFunction: params.isFunction,
exposeUtilityScript: params.exposeUtilityScript
}, (0, _jsHandleDispatcher.parseArgument)(params.arg)))
};
}
async evaluateExpressionHandle(params, metadata) {
return {
handle: _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(this.parentScope(), await this._frame.evaluateExpressionHandle(params.expression, {
isFunction: params.isFunction
}, (0, _jsHandleDispatcher.parseArgument)(params.arg)))
};
}
async waitForSelector(params, metadata) {
return {
element: _elementHandlerDispatcher.ElementHandleDispatcher.fromNullable(this.parentScope(), await this._frame.waitForSelector(metadata, params.selector, params))
};
}
async dispatchEvent(params, metadata) {
return this._frame.dispatchEvent(metadata, params.selector, params.type, (0, _jsHandleDispatcher.parseArgument)(params.eventInit), params);
}
async evalOnSelector(params, metadata) {
return {
value: (0, _jsHandleDispatcher.serializeResult)(await this._frame.evalOnSelector(params.selector, !!params.strict, params.expression, params.isFunction, (0, _jsHandleDispatcher.parseArgument)(params.arg)))
};
}
async evalOnSelectorAll(params, metadata) {
return {
value: (0, _jsHandleDispatcher.serializeResult)(await this._frame.evalOnSelectorAll(params.selector, params.expression, params.isFunction, (0, _jsHandleDispatcher.parseArgument)(params.arg)))
};
}
async querySelector(params, metadata) {
return {
element: _elementHandlerDispatcher.ElementHandleDispatcher.fromNullable(this.parentScope(), await this._frame.querySelector(params.selector, params))
};
}
async querySelectorAll(params, metadata) {
const elements = await this._frame.querySelectorAll(params.selector);
return {
elements: elements.map(e => _elementHandlerDispatcher.ElementHandleDispatcher.from(this.parentScope(), e))
};
}
async queryCount(params) {
return {
value: await this._frame.queryCount(params.selector)
};
}
async content() {
return {
value: await this._frame.content()
};
}
async setContent(params, metadata) {
return await this._frame.setContent(metadata, params.html, params);
}
async addScriptTag(params, metadata) {
return {
element: _elementHandlerDispatcher.ElementHandleDispatcher.from(this.parentScope(), await this._frame.addScriptTag(params))
};
}
async addStyleTag(params, metadata) {
return {
element: _elementHandlerDispatcher.ElementHandleDispatcher.from(this.parentScope(), await this._frame.addStyleTag(params))
};
}
async click(params, metadata) {
return await this._frame.click(metadata, params.selector, params);
}
async dblclick(params, metadata) {
return await this._frame.dblclick(metadata, params.selector, params);
}
async dragAndDrop(params, metadata) {
return await this._frame.dragAndDrop(metadata, params.source, params.target, params);
}
async tap(params, metadata) {
return await this._frame.tap(metadata, params.selector, params);
}
async fill(params, metadata) {
return await this._frame.fill(metadata, params.selector, params.value, params);
}
async focus(params, metadata) {
await this._frame.focus(metadata, params.selector, params);
}
async blur(params, metadata) {
await this._frame.blur(metadata, params.selector, params);
}
async textContent(params, metadata) {
const value = await this._frame.textContent(metadata, params.selector, params);
return {
value: value === null ? undefined : value
};
}
async innerText(params, metadata) {
return {
value: await this._frame.innerText(metadata, params.selector, params)
};
}
async innerHTML(params, metadata) {
return {
value: await this._frame.innerHTML(metadata, params.selector, params)
};
}
async getAttribute(params, metadata) {
const value = await this._frame.getAttribute(metadata, params.selector, params.name, params);
return {
value: value === null ? undefined : value
};
}
async inputValue(params, metadata) {
const value = await this._frame.inputValue(metadata, params.selector, params);
return {
value
};
}
async isChecked(params, metadata) {
return {
value: await this._frame.isChecked(metadata, params.selector, params)
};
}
async isDisabled(params, metadata) {
return {
value: await this._frame.isDisabled(metadata, params.selector, params)
};
}
async isEditable(params, metadata) {
return {
value: await this._frame.isEditable(metadata, params.selector, params)
};
}
async isEnabled(params, metadata) {
return {
value: await this._frame.isEnabled(metadata, params.selector, params)
};
}
async isHidden(params, metadata) {
return {
value: await this._frame.isHidden(metadata, params.selector, params)
};
}
async isVisible(params, metadata) {
return {
value: await this._frame.isVisible(metadata, params.selector, params)
};
}
async hover(params, metadata) {
return await this._frame.hover(metadata, params.selector, params);
}
async selectOption(params, metadata) {
const elements = (params.elements || []).map(e => e._elementHandle);
return {
values: await this._frame.selectOption(metadata, params.selector, elements, params.options || [], params)
};
}
async setInputFiles(params, metadata) {
return await this._frame.setInputFiles(metadata, params.selector, {
files: params.files
}, params);
}
async setInputFilePaths(params, metadata) {
let {
localPaths
} = params;
if (!localPaths) {
if (!params.streams) throw new Error('Neither localPaths nor streams is specified');
localPaths = params.streams.map(c => c.path());
}
for (const p of localPaths) (0, _utils.assert)(_path.default.isAbsolute(p) && _path.default.resolve(p) === p, 'Paths provided to localPaths must be absolute and fully resolved.');
return await this._frame.setInputFiles(metadata, params.selector, {
localPaths
}, params);
}
async type(params, metadata) {
return await this._frame.type(metadata, params.selector, params.text, params);
}
async press(params, metadata) {
return await this._frame.press(metadata, params.selector, params.key, params);
}
async check(params, metadata) {
return await this._frame.check(metadata, params.selector, params);
}
async uncheck(params, metadata) {
return await this._frame.uncheck(metadata, params.selector, params);
}
async waitForTimeout(params, metadata) {
return await this._frame.waitForTimeout(metadata, params.timeout);
}
async waitForFunction(params, metadata) {
return {
handle: _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(this.parentScope(), await this._frame._waitForFunctionExpression(metadata, params.expression, params.isFunction, (0, _jsHandleDispatcher.parseArgument)(params.arg), params))
};
}
async title(params, metadata) {
return {
value: await this._frame.title()
};
}
async highlight(params, metadata) {
return await this._frame.highlight(params.selector);
}
async expect(params, metadata) {
const expectedValue = params.expectedValue ? (0, _jsHandleDispatcher.parseArgument)(params.expectedValue) : undefined;
const result = await this._frame.expect(metadata, params.selector, {
...params,
expectedValue
});
if (result.received !== undefined) result.received = (0, _jsHandleDispatcher.serializeResult)(result.received);
if (result.matches === params.isNot) metadata.error = {
error: {
name: 'Expect',
message: 'Expect failed'
}
};
return result;
}
}
exports.FrameDispatcher = FrameDispatcher;

View File

@@ -0,0 +1,100 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.JSHandleDispatcher = void 0;
exports.parseArgument = parseArgument;
exports.parseValue = parseValue;
exports.serializeResult = serializeResult;
var _dispatcher = require("./dispatcher");
var _elementHandlerDispatcher = require("./elementHandlerDispatcher");
var _serializers = require("../../protocol/serializers");
/**
* 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 JSHandleDispatcher extends _dispatcher.Dispatcher {
constructor(scope, jsHandle) {
// Do not call this directly, use createHandle() instead.
super(scope, jsHandle, jsHandle.asElement() ? 'ElementHandle' : 'JSHandle', {
preview: jsHandle.toString()
});
this._type_JSHandle = true;
jsHandle._setPreviewCallback(preview => this._dispatchEvent('previewUpdated', {
preview
}));
}
async evaluateExpression(params) {
return {
value: serializeResult(await this._object.evaluateExpression(params.expression, {
isFunction: params.isFunction
}, parseArgument(params.arg)))
};
}
async evaluateExpressionHandle(params) {
const jsHandle = await this._object.evaluateExpressionHandle(params.expression, {
isFunction: params.isFunction
}, parseArgument(params.arg));
return {
handle: _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(this.parentScope(), jsHandle)
};
}
async getProperty(params) {
const jsHandle = await this._object.getProperty(params.name);
return {
handle: _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(this.parentScope(), jsHandle)
};
}
async getPropertyList() {
const map = await this._object.getProperties();
const properties = [];
for (const [name, value] of map) properties.push({
name,
value: _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(this.parentScope(), value)
});
return {
properties
};
}
async jsonValue() {
return {
value: serializeResult(await this._object.jsonValue())
};
}
async objectCount(params) {
return {
count: await this._object.objectCount()
};
}
async dispose() {
await this._object.dispose();
}
}
// Generic channel parser converts guids to JSHandleDispatchers,
// and this function takes care of coverting them into underlying JSHandles.
exports.JSHandleDispatcher = JSHandleDispatcher;
function parseArgument(arg) {
return (0, _serializers.parseSerializedValue)(arg.value, arg.handles.map(a => a._object));
}
function parseValue(v) {
return (0, _serializers.parseSerializedValue)(v, []);
}
function serializeResult(arg) {
return (0, _serializers.serializeValue)(arg, value => ({
fallThrough: value
}));
}

View File

@@ -0,0 +1,61 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.JsonPipeDispatcher = void 0;
var _dispatcher = require("./dispatcher");
var _utils = require("../../utils");
var _serializers = require("../../protocol/serializers");
/**
* 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 JsonPipeDispatcher extends _dispatcher.Dispatcher {
constructor(scope) {
super(scope, {
guid: 'jsonPipe@' + (0, _utils.createGuid)()
}, 'JsonPipe', {});
this._type_JsonPipe = true;
}
async send(params) {
this.emit('message', params.message);
}
async close() {
this.emit('close');
if (!this._disposed) {
this._dispatchEvent('closed', {});
this._dispose();
}
}
dispatch(message) {
if (!this._disposed) this._dispatchEvent('message', {
message
});
}
wasClosed(error) {
if (!this._disposed) {
const params = error ? {
error: (0, _serializers.serializeError)(error)
} : {};
this._dispatchEvent('closed', params);
this._dispose();
}
}
dispose() {
this._dispose();
}
}
exports.JsonPipeDispatcher = JsonPipeDispatcher;

View File

@@ -0,0 +1,392 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.LocalUtilsDispatcher = void 0;
exports.urlToWSEndpoint = urlToWSEndpoint;
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
var _os = _interopRequireDefault(require("os"));
var _manualPromise = require("../../utils/manualPromise");
var _utils = require("../../utils");
var _dispatcher = require("./dispatcher");
var _zipBundle = require("../../zipBundle");
var _zipFile = require("../../utils/zipFile");
var _jsonPipeDispatcher = require("../dispatchers/jsonPipeDispatcher");
var _transport = require("../transport");
var _socksInterceptor = require("../socksInterceptor");
var _userAgent = require("../../utils/userAgent");
var _progress = require("../progress");
var _network = require("../../utils/network");
var _instrumentation = require("../../server/instrumentation");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* 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 LocalUtilsDispatcher extends _dispatcher.Dispatcher {
constructor(scope, playwright) {
const localUtils = new _instrumentation.SdkObject(playwright, 'localUtils', 'localUtils');
super(scope, localUtils, 'LocalUtils', {});
this._type_LocalUtils = void 0;
this._harBackends = new Map();
this._stackSessions = new Map();
this._type_LocalUtils = true;
}
async zip(params) {
const promise = new _manualPromise.ManualPromise();
const zipFile = new _zipBundle.yazl.ZipFile();
zipFile.on('error', error => promise.reject(error));
const addFile = (file, name) => {
try {
if (_fs.default.statSync(file).isFile()) zipFile.addFile(file, name);
} catch (e) {}
};
for (const entry of params.entries) addFile(entry.value, entry.name);
// Add stacks and the sources.
const stackSession = params.stacksId ? this._stackSessions.get(params.stacksId) : undefined;
if (stackSession !== null && stackSession !== void 0 && stackSession.callStacks.length) {
await stackSession.writer;
if (process.env.PW_LIVE_TRACE_STACKS) {
zipFile.addFile(stackSession.file, 'trace.stacks');
} else {
const buffer = Buffer.from(JSON.stringify((0, _utils.serializeClientSideCallMetadata)(stackSession.callStacks)));
zipFile.addBuffer(buffer, 'trace.stacks');
}
}
// Collect sources from stacks.
if (params.includeSources) {
const sourceFiles = new Set();
for (const {
stack
} of (stackSession === null || stackSession === void 0 ? void 0 : stackSession.callStacks) || []) {
if (!stack) continue;
for (const {
file
} of stack) sourceFiles.add(file);
}
for (const sourceFile of sourceFiles) addFile(sourceFile, 'resources/src@' + (0, _utils.calculateSha1)(sourceFile) + '.txt');
}
if (params.mode === 'write') {
// New file, just compress the entries.
await _fs.default.promises.mkdir(_path.default.dirname(params.zipFile), {
recursive: true
});
zipFile.end(undefined, () => {
zipFile.outputStream.pipe(_fs.default.createWriteStream(params.zipFile)).on('close', () => promise.resolve());
});
await promise;
await this._deleteStackSession(params.stacksId);
return;
}
// File already exists. Repack and add new entries.
const tempFile = params.zipFile + '.tmp';
await _fs.default.promises.rename(params.zipFile, tempFile);
_zipBundle.yauzl.open(tempFile, (err, inZipFile) => {
if (err) {
promise.reject(err);
return;
}
(0, _utils.assert)(inZipFile);
let pendingEntries = inZipFile.entryCount;
inZipFile.on('entry', entry => {
inZipFile.openReadStream(entry, (err, readStream) => {
if (err) {
promise.reject(err);
return;
}
zipFile.addReadStream(readStream, entry.fileName);
if (--pendingEntries === 0) {
zipFile.end(undefined, () => {
zipFile.outputStream.pipe(_fs.default.createWriteStream(params.zipFile)).on('close', () => {
_fs.default.promises.unlink(tempFile).then(() => {
promise.resolve();
});
});
});
}
});
});
});
await promise;
await this._deleteStackSession(params.stacksId);
}
async harOpen(params, metadata) {
let harBackend;
if (params.file.endsWith('.zip')) {
const zipFile = new _zipFile.ZipFile(params.file);
const entryNames = await zipFile.entries();
const harEntryName = entryNames.find(e => e.endsWith('.har'));
if (!harEntryName) return {
error: 'Specified archive does not have a .har file'
};
const har = await zipFile.read(harEntryName);
const harFile = JSON.parse(har.toString());
harBackend = new HarBackend(harFile, null, zipFile);
} else {
const harFile = JSON.parse(await _fs.default.promises.readFile(params.file, 'utf-8'));
harBackend = new HarBackend(harFile, _path.default.dirname(params.file), null);
}
this._harBackends.set(harBackend.id, harBackend);
return {
harId: harBackend.id
};
}
async harLookup(params, metadata) {
const harBackend = this._harBackends.get(params.harId);
if (!harBackend) return {
action: 'error',
message: `Internal error: har was not opened`
};
return await harBackend.lookup(params.url, params.method, params.headers, params.postData, params.isNavigationRequest);
}
async harClose(params, metadata) {
const harBackend = this._harBackends.get(params.harId);
if (harBackend) {
this._harBackends.delete(harBackend.id);
harBackend.dispose();
}
}
async harUnzip(params, metadata) {
const dir = _path.default.dirname(params.zipFile);
const zipFile = new _zipFile.ZipFile(params.zipFile);
for (const entry of await zipFile.entries()) {
const buffer = await zipFile.read(entry);
if (entry === 'har.har') await _fs.default.promises.writeFile(params.harFile, buffer);else await _fs.default.promises.writeFile(_path.default.join(dir, entry), buffer);
}
zipFile.close();
await _fs.default.promises.unlink(params.zipFile);
}
async connect(params, metadata) {
const controller = new _progress.ProgressController(metadata, this._object);
controller.setLogName('browser');
return await controller.run(async progress => {
var _params$exposeNetwork;
const wsHeaders = {
'User-Agent': (0, _userAgent.getUserAgent)(),
'x-playwright-proxy': (_params$exposeNetwork = params.exposeNetwork) !== null && _params$exposeNetwork !== void 0 ? _params$exposeNetwork : '',
...params.headers
};
const wsEndpoint = await urlToWSEndpoint(progress, params.wsEndpoint);
const transport = await _transport.WebSocketTransport.connect(progress, wsEndpoint, wsHeaders, true, 'x-playwright-debug-log');
const socksInterceptor = new _socksInterceptor.SocksInterceptor(transport, params.exposeNetwork, params.socksProxyRedirectPortForTest);
const pipe = new _jsonPipeDispatcher.JsonPipeDispatcher(this);
transport.onmessage = json => {
if (socksInterceptor.interceptMessage(json)) return;
const cb = () => {
try {
pipe.dispatch(json);
} catch (e) {
transport.close();
}
};
if (params.slowMo) setTimeout(cb, params.slowMo);else cb();
};
pipe.on('message', message => {
transport.send(message);
});
transport.onclose = () => {
socksInterceptor === null || socksInterceptor === void 0 ? void 0 : socksInterceptor.cleanup();
pipe.wasClosed();
};
pipe.on('close', () => transport.close());
return {
pipe,
headers: transport.headers
};
}, params.timeout || 0);
}
async tracingStarted(params, metadata) {
let tmpDir = undefined;
if (!params.tracesDir) tmpDir = await _fs.default.promises.mkdtemp(_path.default.join(_os.default.tmpdir(), 'playwright-tracing-'));
const traceStacksFile = _path.default.join(params.tracesDir || tmpDir, params.traceName + '.stacks');
this._stackSessions.set(traceStacksFile, {
callStacks: [],
file: traceStacksFile,
writer: Promise.resolve(),
tmpDir
});
return {
stacksId: traceStacksFile
};
}
async traceDiscarded(params, metadata) {
await this._deleteStackSession(params.stacksId);
}
async addStackToTracingNoReply(params, metadata) {
for (const session of this._stackSessions.values()) {
session.callStacks.push(params.callData);
if (process.env.PW_LIVE_TRACE_STACKS) {
session.writer = session.writer.then(() => {
const buffer = Buffer.from(JSON.stringify((0, _utils.serializeClientSideCallMetadata)(session.callStacks)));
return _fs.default.promises.writeFile(session.file, buffer);
});
}
}
}
async _deleteStackSession(stacksId) {
const session = stacksId ? this._stackSessions.get(stacksId) : undefined;
if (!session) return;
await session.writer;
if (session.tmpDir) await (0, _utils.removeFolders)([session.tmpDir]);
this._stackSessions.delete(stacksId);
}
}
exports.LocalUtilsDispatcher = LocalUtilsDispatcher;
const redirectStatus = [301, 302, 303, 307, 308];
class HarBackend {
constructor(harFile, baseDir, zipFile) {
this.id = (0, _utils.createGuid)();
this._harFile = void 0;
this._zipFile = void 0;
this._baseDir = void 0;
this._harFile = harFile;
this._baseDir = baseDir;
this._zipFile = zipFile;
}
async lookup(url, method, headers, postData, isNavigationRequest) {
let entry;
try {
entry = await this._harFindResponse(url, method, headers, postData);
} catch (e) {
return {
action: 'error',
message: 'HAR error: ' + e.message
};
}
if (!entry) return {
action: 'noentry'
};
// If navigation is being redirected, restart it with the final url to ensure the document's url changes.
if (entry.request.url !== url && isNavigationRequest) return {
action: 'redirect',
redirectURL: entry.request.url
};
const response = entry.response;
try {
const buffer = await this._loadContent(response.content);
return {
action: 'fulfill',
status: response.status,
headers: response.headers,
body: buffer
};
} catch (e) {
return {
action: 'error',
message: e.message
};
}
}
async _loadContent(content) {
const file = content._file;
let buffer;
if (file) {
if (this._zipFile) buffer = await this._zipFile.read(file);else buffer = await _fs.default.promises.readFile(_path.default.resolve(this._baseDir, file));
} else {
buffer = Buffer.from(content.text || '', content.encoding === 'base64' ? 'base64' : 'utf-8');
}
return buffer;
}
async _harFindResponse(url, method, headers, postData) {
const harLog = this._harFile.log;
const visited = new Set();
while (true) {
const entries = [];
for (const candidate of harLog.entries) {
if (candidate.request.url !== url || candidate.request.method !== method) continue;
if (method === 'POST' && postData && candidate.request.postData) {
const buffer = await this._loadContent(candidate.request.postData);
if (!buffer.equals(postData)) continue;
}
entries.push(candidate);
}
if (!entries.length) return;
let entry = entries[0];
// Disambiguate using headers - then one with most matching headers wins.
if (entries.length > 1) {
const list = [];
for (const candidate of entries) {
const matchingHeaders = countMatchingHeaders(candidate.request.headers, headers);
list.push({
candidate,
matchingHeaders
});
}
list.sort((a, b) => b.matchingHeaders - a.matchingHeaders);
entry = list[0].candidate;
}
if (visited.has(entry)) throw new Error(`Found redirect cycle for ${url}`);
visited.add(entry);
// Follow redirects.
const locationHeader = entry.response.headers.find(h => h.name.toLowerCase() === 'location');
if (redirectStatus.includes(entry.response.status) && locationHeader) {
const locationURL = new URL(locationHeader.value, url);
url = locationURL.toString();
if ((entry.response.status === 301 || entry.response.status === 302) && method === 'POST' || entry.response.status === 303 && !['GET', 'HEAD'].includes(method)) {
// HTTP-redirect fetch step 13 (https://fetch.spec.whatwg.org/#http-redirect-fetch)
method = 'GET';
}
continue;
}
return entry;
}
}
dispose() {
var _this$_zipFile;
(_this$_zipFile = this._zipFile) === null || _this$_zipFile === void 0 ? void 0 : _this$_zipFile.close();
}
}
function countMatchingHeaders(harHeaders, headers) {
const set = new Set(headers.map(h => h.name.toLowerCase() + ':' + h.value));
let matches = 0;
for (const h of harHeaders) {
if (set.has(h.name.toLowerCase() + ':' + h.value)) ++matches;
}
return matches;
}
async function urlToWSEndpoint(progress, endpointURL) {
var _progress$timeUntilDe;
if (endpointURL.startsWith('ws')) return endpointURL;
progress === null || progress === void 0 ? void 0 : progress.log(`<ws preparing> retrieving websocket url from ${endpointURL}`);
const fetchUrl = new URL(endpointURL);
if (!fetchUrl.pathname.endsWith('/')) fetchUrl.pathname += '/';
fetchUrl.pathname += 'json';
const json = await (0, _network.fetchData)({
url: fetchUrl.toString(),
method: 'GET',
timeout: (_progress$timeUntilDe = progress === null || progress === void 0 ? void 0 : progress.timeUntilDeadline()) !== null && _progress$timeUntilDe !== void 0 ? _progress$timeUntilDe : 30_000,
headers: {
'User-Agent': (0, _userAgent.getUserAgent)()
}
}, async (params, response) => {
return new Error(`Unexpected status ${response.statusCode} when connecting to ${fetchUrl.toString()}.\n` + `This does not look like a Playwright server, try connecting via ws://.`);
});
progress === null || progress === void 0 ? void 0 : progress.throwIfAborted();
const wsUrl = new URL(endpointURL);
let wsEndpointPath = JSON.parse(json).wsEndpointPath;
if (wsEndpointPath.startsWith('/')) wsEndpointPath = wsEndpointPath.substring(1);
if (!wsUrl.pathname.endsWith('/')) wsUrl.pathname += '/';
wsUrl.pathname += wsEndpointPath;
wsUrl.protocol = wsUrl.protocol === 'https:' ? 'wss:' : 'ws:';
return wsUrl.toString();
}

View File

@@ -0,0 +1,213 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.WebSocketDispatcher = exports.RouteDispatcher = exports.ResponseDispatcher = exports.RequestDispatcher = exports.APIRequestContextDispatcher = void 0;
var _network = require("../network");
var _dispatcher = require("./dispatcher");
var _tracingDispatcher = require("./tracingDispatcher");
var _frameDispatcher = require("./frameDispatcher");
var _pageDispatcher = require("./pageDispatcher");
/**
* 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 RequestDispatcher extends _dispatcher.Dispatcher {
static from(scope, request) {
const result = (0, _dispatcher.existingDispatcher)(request);
return result || new RequestDispatcher(scope, request);
}
static fromNullable(scope, request) {
return request ? RequestDispatcher.from(scope, request) : undefined;
}
constructor(scope, request) {
const postData = request.postDataBuffer();
super(scope, request, 'Request', {
frame: _frameDispatcher.FrameDispatcher.fromNullable(scope, request.frame()),
serviceWorker: _pageDispatcher.WorkerDispatcher.fromNullable(scope, request.serviceWorker()),
url: request.url(),
resourceType: request.resourceType(),
method: request.method(),
postData: postData === null ? undefined : postData,
headers: request.headers(),
isNavigationRequest: request.isNavigationRequest(),
redirectedFrom: RequestDispatcher.fromNullable(scope, request.redirectedFrom())
});
this._type_Request = void 0;
this._type_Request = true;
}
async rawRequestHeaders(params) {
return {
headers: await this._object.rawRequestHeaders()
};
}
async response() {
return {
response: ResponseDispatcher.fromNullable(this.parentScope(), await this._object.response())
};
}
}
exports.RequestDispatcher = RequestDispatcher;
class ResponseDispatcher extends _dispatcher.Dispatcher {
static from(scope, response) {
const result = (0, _dispatcher.existingDispatcher)(response);
return result || new ResponseDispatcher(scope, response);
}
static fromNullable(scope, response) {
return response ? ResponseDispatcher.from(scope, response) : undefined;
}
constructor(scope, response) {
super(scope, response, 'Response', {
// TODO: responses in popups can point to non-reported requests.
request: RequestDispatcher.from(scope, response.request()),
url: response.url(),
status: response.status(),
statusText: response.statusText(),
headers: response.headers(),
timing: response.timing(),
fromServiceWorker: response.fromServiceWorker()
});
this._type_Response = true;
}
async body() {
return {
binary: await this._object.body()
};
}
async securityDetails() {
return {
value: (await this._object.securityDetails()) || undefined
};
}
async serverAddr() {
return {
value: (await this._object.serverAddr()) || undefined
};
}
async rawResponseHeaders(params) {
return {
headers: await this._object.rawResponseHeaders()
};
}
async sizes(params) {
return {
sizes: await this._object.sizes()
};
}
}
exports.ResponseDispatcher = ResponseDispatcher;
class RouteDispatcher extends _dispatcher.Dispatcher {
static from(scope, route) {
const result = (0, _dispatcher.existingDispatcher)(route);
return result || new RouteDispatcher(scope, route);
}
constructor(scope, route) {
super(scope, route, 'Route', {
// Context route can point to a non-reported request.
request: scope
});
this._type_Route = true;
}
async continue(params, metadata) {
// Used to discriminate between continue in tracing.
await this._object.continue({
url: params.url,
method: params.method,
headers: params.headers,
postData: params.postData,
isFallback: params.isFallback
});
}
async fulfill(params, metadata) {
// Used to discriminate between fulfills in tracing.
await this._object.fulfill(params);
}
async abort(params, metadata) {
// Used to discriminate between abort in tracing.
await this._object.abort(params.errorCode || 'failed');
}
async redirectNavigationRequest(params) {
await this._object.redirectNavigationRequest(params.url);
}
}
exports.RouteDispatcher = RouteDispatcher;
class WebSocketDispatcher extends _dispatcher.Dispatcher {
constructor(scope, webSocket) {
super(scope, webSocket, 'WebSocket', {
url: webSocket.url()
});
this._type_EventTarget = true;
this._type_WebSocket = true;
this.addObjectListener(_network.WebSocket.Events.FrameSent, event => this._dispatchEvent('frameSent', event));
this.addObjectListener(_network.WebSocket.Events.FrameReceived, event => this._dispatchEvent('frameReceived', event));
this.addObjectListener(_network.WebSocket.Events.SocketError, error => this._dispatchEvent('socketError', {
error
}));
this.addObjectListener(_network.WebSocket.Events.Close, () => this._dispatchEvent('close', {}));
}
}
exports.WebSocketDispatcher = WebSocketDispatcher;
class APIRequestContextDispatcher extends _dispatcher.Dispatcher {
static from(scope, request) {
const result = (0, _dispatcher.existingDispatcher)(request);
return result || new APIRequestContextDispatcher(scope, request);
}
static fromNullable(scope, request) {
return request ? APIRequestContextDispatcher.from(scope, request) : undefined;
}
constructor(parentScope, request) {
// We will reparent these to the context below.
const tracing = _tracingDispatcher.TracingDispatcher.from(parentScope, request.tracing());
super(parentScope, request, 'APIRequestContext', {
tracing
});
this._type_APIRequestContext = true;
this.adopt(tracing);
}
async storageState(params) {
return this._object.storageState();
}
async dispose(params) {
await this._object.dispose();
}
async fetch(params, metadata) {
const fetchResponse = await this._object.fetch(params, metadata);
return {
response: {
url: fetchResponse.url,
status: fetchResponse.status,
statusText: fetchResponse.statusText,
headers: fetchResponse.headers,
fetchUid: fetchResponse.fetchUid
}
};
}
async fetchResponseBody(params) {
return {
binary: this._object.fetchResponses.get(params.fetchUid)
};
}
async fetchLog(params) {
const log = this._object.fetchLog.get(params.fetchUid) || [];
return {
log
};
}
async disposeAPIResponse(params) {
this._object.disposeResponse(params.fetchUid);
}
}
exports.APIRequestContextDispatcher = APIRequestContextDispatcher;

View File

@@ -0,0 +1,351 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.WorkerDispatcher = exports.PageDispatcher = exports.BindingCallDispatcher = void 0;
var _page = require("../page");
var _dispatcher = require("./dispatcher");
var _serializers = require("../../protocol/serializers");
var _frameDispatcher = require("./frameDispatcher");
var _networkDispatchers = require("./networkDispatchers");
var _jsHandleDispatcher = require("./jsHandleDispatcher");
var _elementHandlerDispatcher = require("./elementHandlerDispatcher");
var _artifactDispatcher = require("./artifactDispatcher");
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 PageDispatcher extends _dispatcher.Dispatcher {
static from(parentScope, page) {
return PageDispatcher.fromNullable(parentScope, page);
}
static fromNullable(parentScope, page) {
if (!page) return undefined;
const result = (0, _dispatcher.existingDispatcher)(page);
return result || new PageDispatcher(parentScope, page);
}
constructor(parentScope, page) {
// TODO: theoretically, there could be more than one frame already.
// If we split pageCreated and pageReady, there should be no main frame during pageCreated.
// We will reparent it to the page below using adopt.
const mainFrame = _frameDispatcher.FrameDispatcher.from(parentScope, page.mainFrame());
super(parentScope, page, 'Page', {
mainFrame,
viewportSize: page.viewportSize() || undefined,
isClosed: page.isClosed(),
opener: PageDispatcher.fromNullable(parentScope, page.opener())
});
this._type_EventTarget = true;
this._type_Page = true;
this._page = void 0;
this._subscriptions = new Set();
this.adopt(mainFrame);
this._page = page;
this.addObjectListener(_page.Page.Events.Close, () => {
this._dispatchEvent('close');
this._dispose();
});
this.addObjectListener(_page.Page.Events.Crash, () => this._dispatchEvent('crash'));
this.addObjectListener(_page.Page.Events.Download, download => {
// Artifact can outlive the page, so bind to the context scope.
this._dispatchEvent('download', {
url: download.url,
suggestedFilename: download.suggestedFilename(),
artifact: _artifactDispatcher.ArtifactDispatcher.from(parentScope, download.artifact)
});
});
this.addObjectListener(_page.Page.Events.FileChooser, fileChooser => this._dispatchEvent('fileChooser', {
element: _elementHandlerDispatcher.ElementHandleDispatcher.from(this, fileChooser.element()),
isMultiple: fileChooser.isMultiple()
}));
this.addObjectListener(_page.Page.Events.FrameAttached, frame => this._onFrameAttached(frame));
this.addObjectListener(_page.Page.Events.FrameDetached, frame => this._onFrameDetached(frame));
this.addObjectListener(_page.Page.Events.PageError, error => this._dispatchEvent('pageError', {
error: (0, _serializers.serializeError)(error)
}));
this.addObjectListener(_page.Page.Events.WebSocket, webSocket => this._dispatchEvent('webSocket', {
webSocket: new _networkDispatchers.WebSocketDispatcher(this, webSocket)
}));
this.addObjectListener(_page.Page.Events.Worker, worker => this._dispatchEvent('worker', {
worker: new WorkerDispatcher(this, worker)
}));
this.addObjectListener(_page.Page.Events.Video, artifact => this._dispatchEvent('video', {
artifact: _artifactDispatcher.ArtifactDispatcher.from(parentScope, artifact)
}));
if (page._video) this._dispatchEvent('video', {
artifact: _artifactDispatcher.ArtifactDispatcher.from(this.parentScope(), page._video)
});
// Ensure client knows about all frames.
const frames = page._frameManager.frames();
for (let i = 1; i < frames.length; i++) this._onFrameAttached(frames[i]);
}
page() {
return this._page;
}
async setDefaultNavigationTimeoutNoReply(params, metadata) {
this._page.setDefaultNavigationTimeout(params.timeout);
}
async setDefaultTimeoutNoReply(params, metadata) {
this._page.setDefaultTimeout(params.timeout);
}
async exposeBinding(params, metadata) {
await this._page.exposeBinding(params.name, !!params.needsHandle, (source, ...args) => {
// When reusing the context, we might have some bindings called late enough,
// after context and page dispatchers have been disposed.
if (this._disposed) return;
const binding = new BindingCallDispatcher(this, params.name, !!params.needsHandle, source, args);
this._dispatchEvent('bindingCall', {
binding
});
return binding.promise();
});
}
async setExtraHTTPHeaders(params, metadata) {
await this._page.setExtraHTTPHeaders(params.headers);
}
async reload(params, metadata) {
return {
response: _networkDispatchers.ResponseDispatcher.fromNullable(this.parentScope(), await this._page.reload(metadata, params))
};
}
async goBack(params, metadata) {
return {
response: _networkDispatchers.ResponseDispatcher.fromNullable(this.parentScope(), await this._page.goBack(metadata, params))
};
}
async goForward(params, metadata) {
return {
response: _networkDispatchers.ResponseDispatcher.fromNullable(this.parentScope(), await this._page.goForward(metadata, params))
};
}
async emulateMedia(params, metadata) {
await this._page.emulateMedia({
media: params.media,
colorScheme: params.colorScheme,
reducedMotion: params.reducedMotion,
forcedColors: params.forcedColors
});
}
async setViewportSize(params, metadata) {
await this._page.setViewportSize(params.viewportSize);
}
async addInitScript(params, metadata) {
await this._page.addInitScript(params.source);
}
async setNetworkInterceptionPatterns(params, metadata) {
if (!params.patterns.length) {
await this._page.setClientRequestInterceptor(undefined);
return;
}
const urlMatchers = params.patterns.map(pattern => pattern.regexSource ? new RegExp(pattern.regexSource, pattern.regexFlags) : pattern.glob);
await this._page.setClientRequestInterceptor((route, request) => {
const matchesSome = urlMatchers.some(urlMatch => (0, _utils.urlMatches)(this._page._browserContext._options.baseURL, request.url(), urlMatch));
if (!matchesSome) return false;
this._dispatchEvent('route', {
route: _networkDispatchers.RouteDispatcher.from(_networkDispatchers.RequestDispatcher.from(this.parentScope(), request), route)
});
return true;
});
}
async expectScreenshot(params, metadata) {
var _params$screenshotOpt, _params$comparatorOpt;
const mask = (((_params$screenshotOpt = params.screenshotOptions) === null || _params$screenshotOpt === void 0 ? void 0 : _params$screenshotOpt.mask) || []).map(({
frame,
selector
}) => ({
frame: frame._object,
selector
}));
const locator = params.locator ? {
frame: params.locator.frame._object,
selector: params.locator.selector
} : undefined;
return await this._page.expectScreenshot(metadata, {
...params,
locator,
comparatorOptions: {
...params.comparatorOptions,
_comparator: (_params$comparatorOpt = params.comparatorOptions) === null || _params$comparatorOpt === void 0 ? void 0 : _params$comparatorOpt.comparator
},
screenshotOptions: {
...params.screenshotOptions,
mask
}
});
}
async screenshot(params, metadata) {
const mask = (params.mask || []).map(({
frame,
selector
}) => ({
frame: frame._object,
selector
}));
return {
binary: await this._page.screenshot(metadata, {
...params,
mask
})
};
}
async close(params, metadata) {
await this._page.close(metadata, params);
}
async updateSubscription(params) {
if (params.event === 'fileChooser') await this._page.setFileChooserIntercepted(params.enabled);
if (params.enabled) this._subscriptions.add(params.event);else this._subscriptions.delete(params.event);
}
async keyboardDown(params, metadata) {
await this._page.keyboard.down(params.key);
}
async keyboardUp(params, metadata) {
await this._page.keyboard.up(params.key);
}
async keyboardInsertText(params, metadata) {
await this._page.keyboard.insertText(params.text);
}
async keyboardType(params, metadata) {
await this._page.keyboard.type(params.text, params);
}
async keyboardPress(params, metadata) {
await this._page.keyboard.press(params.key, params);
}
async mouseMove(params, metadata) {
await this._page.mouse.move(params.x, params.y, params);
}
async mouseDown(params, metadata) {
await this._page.mouse.down(params);
}
async mouseUp(params, metadata) {
await this._page.mouse.up(params);
}
async mouseClick(params, metadata) {
await this._page.mouse.click(params.x, params.y, params);
}
async mouseWheel(params, metadata) {
await this._page.mouse.wheel(params.deltaX, params.deltaY);
}
async touchscreenTap(params, metadata) {
await this._page.touchscreen.tap(params.x, params.y);
}
async accessibilitySnapshot(params, metadata) {
const rootAXNode = await this._page.accessibility.snapshot({
interestingOnly: params.interestingOnly,
root: params.root ? params.root._elementHandle : undefined
});
return {
rootAXNode: rootAXNode || undefined
};
}
async pdf(params, metadata) {
if (!this._page.pdf) throw new Error('PDF generation is only supported for Headless Chromium');
const buffer = await this._page.pdf(params);
return {
pdf: buffer
};
}
async bringToFront(params, metadata) {
await this._page.bringToFront();
}
async startJSCoverage(params, metadata) {
const coverage = this._page.coverage;
await coverage.startJSCoverage(params);
}
async stopJSCoverage(params, metadata) {
const coverage = this._page.coverage;
return await coverage.stopJSCoverage();
}
async startCSSCoverage(params, metadata) {
const coverage = this._page.coverage;
await coverage.startCSSCoverage(params);
}
async stopCSSCoverage(params, metadata) {
const coverage = this._page.coverage;
return await coverage.stopCSSCoverage();
}
_onFrameAttached(frame) {
this._dispatchEvent('frameAttached', {
frame: _frameDispatcher.FrameDispatcher.from(this, frame)
});
}
_onFrameDetached(frame) {
this._dispatchEvent('frameDetached', {
frame: _frameDispatcher.FrameDispatcher.from(this, frame)
});
}
_onDispose() {
// Avoid protocol calls for the closed page.
if (!this._page.isClosedOrClosingOrCrashed()) this._page.setClientRequestInterceptor(undefined).catch(() => {});
}
}
exports.PageDispatcher = PageDispatcher;
class WorkerDispatcher extends _dispatcher.Dispatcher {
static fromNullable(scope, worker) {
if (!worker) return undefined;
const result = (0, _dispatcher.existingDispatcher)(worker);
return result || new WorkerDispatcher(scope, worker);
}
constructor(scope, worker) {
super(scope, worker, 'Worker', {
url: worker.url()
});
this._type_Worker = true;
this.addObjectListener(_page.Worker.Events.Close, () => this._dispatchEvent('close'));
}
async evaluateExpression(params, metadata) {
return {
value: (0, _jsHandleDispatcher.serializeResult)(await this._object.evaluateExpression(params.expression, params.isFunction, (0, _jsHandleDispatcher.parseArgument)(params.arg)))
};
}
async evaluateExpressionHandle(params, metadata) {
return {
handle: _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(this, await this._object.evaluateExpressionHandle(params.expression, params.isFunction, (0, _jsHandleDispatcher.parseArgument)(params.arg)))
};
}
}
exports.WorkerDispatcher = WorkerDispatcher;
class BindingCallDispatcher extends _dispatcher.Dispatcher {
constructor(scope, name, needsHandle, source, args) {
super(scope, {
guid: 'bindingCall@' + (0, _utils.createGuid)()
}, 'BindingCall', {
frame: _frameDispatcher.FrameDispatcher.from(scope, source.frame),
name,
args: needsHandle ? undefined : args.map(_jsHandleDispatcher.serializeResult),
handle: needsHandle ? _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(scope, args[0]) : undefined
});
this._type_BindingCall = true;
this._resolve = void 0;
this._reject = void 0;
this._promise = void 0;
this._promise = new Promise((resolve, reject) => {
this._resolve = resolve;
this._reject = reject;
});
}
promise() {
return this._promise;
}
async resolve(params, metadata) {
this._resolve((0, _jsHandleDispatcher.parseArgument)(params.result));
}
async reject(params, metadata) {
this._reject((0, _serializers.parseError)(params.error));
}
}
exports.BindingCallDispatcher = BindingCallDispatcher;

View File

@@ -0,0 +1,111 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.PlaywrightDispatcher = void 0;
var _fetch = require("../fetch");
var _socksProxy = require("../../common/socksProxy");
var _androidDispatcher = require("./androidDispatcher");
var _browserTypeDispatcher = require("./browserTypeDispatcher");
var _dispatcher = require("./dispatcher");
var _electronDispatcher = require("./electronDispatcher");
var _localUtilsDispatcher = require("./localUtilsDispatcher");
var _networkDispatchers = require("./networkDispatchers");
var _selectorsDispatcher = require("./selectorsDispatcher");
var _browserDispatcher = require("./browserDispatcher");
var _utils = require("../../utils");
var _eventsHelper = require("../../utils/eventsHelper");
/**
* 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 PlaywrightDispatcher extends _dispatcher.Dispatcher {
constructor(scope, playwright, socksProxy, preLaunchedBrowser, prelaunchedAndroidDevice) {
const descriptors = require('../deviceDescriptors');
const deviceDescriptors = Object.entries(descriptors).map(([name, descriptor]) => ({
name,
descriptor
}));
const browserDispatcher = preLaunchedBrowser ? new _browserDispatcher.ConnectedBrowserDispatcher(scope, preLaunchedBrowser) : undefined;
const android = new _androidDispatcher.AndroidDispatcher(scope, playwright.android);
const prelaunchedAndroidDeviceDispatcher = prelaunchedAndroidDevice ? new _androidDispatcher.AndroidDeviceDispatcher(android, prelaunchedAndroidDevice) : undefined;
super(scope, playwright, 'Playwright', {
chromium: new _browserTypeDispatcher.BrowserTypeDispatcher(scope, playwright.chromium),
firefox: new _browserTypeDispatcher.BrowserTypeDispatcher(scope, playwright.firefox),
webkit: new _browserTypeDispatcher.BrowserTypeDispatcher(scope, playwright.webkit),
android,
electron: new _electronDispatcher.ElectronDispatcher(scope, playwright.electron),
utils: new _localUtilsDispatcher.LocalUtilsDispatcher(scope, playwright),
deviceDescriptors,
selectors: new _selectorsDispatcher.SelectorsDispatcher(scope, (browserDispatcher === null || browserDispatcher === void 0 ? void 0 : browserDispatcher.selectors) || playwright.selectors),
preLaunchedBrowser: browserDispatcher,
preConnectedAndroidDevice: prelaunchedAndroidDeviceDispatcher,
socksSupport: socksProxy ? new SocksSupportDispatcher(scope, socksProxy) : undefined
});
this._type_Playwright = void 0;
this._browserDispatcher = void 0;
this._type_Playwright = true;
this._browserDispatcher = browserDispatcher;
}
async newRequest(params) {
const request = new _fetch.GlobalAPIRequestContext(this._object, params);
return {
request: _networkDispatchers.APIRequestContextDispatcher.from(this.parentScope(), request)
};
}
async cleanup() {
var _this$_browserDispatc;
// Cleanup contexts upon disconnect.
await ((_this$_browserDispatc = this._browserDispatcher) === null || _this$_browserDispatc === void 0 ? void 0 : _this$_browserDispatc.cleanupContexts());
}
}
exports.PlaywrightDispatcher = PlaywrightDispatcher;
class SocksSupportDispatcher extends _dispatcher.Dispatcher {
constructor(scope, socksProxy) {
super(scope, {
guid: 'socksSupport@' + (0, _utils.createGuid)()
}, 'SocksSupport', {});
this._type_SocksSupport = void 0;
this._socksProxy = void 0;
this._socksListeners = void 0;
this._type_SocksSupport = true;
this._socksProxy = socksProxy;
this._socksListeners = [_eventsHelper.eventsHelper.addEventListener(socksProxy, _socksProxy.SocksProxy.Events.SocksRequested, payload => this._dispatchEvent('socksRequested', payload)), _eventsHelper.eventsHelper.addEventListener(socksProxy, _socksProxy.SocksProxy.Events.SocksData, payload => this._dispatchEvent('socksData', payload)), _eventsHelper.eventsHelper.addEventListener(socksProxy, _socksProxy.SocksProxy.Events.SocksClosed, payload => this._dispatchEvent('socksClosed', payload))];
}
async socksConnected(params) {
var _this$_socksProxy;
(_this$_socksProxy = this._socksProxy) === null || _this$_socksProxy === void 0 ? void 0 : _this$_socksProxy.socketConnected(params);
}
async socksFailed(params) {
var _this$_socksProxy2;
(_this$_socksProxy2 = this._socksProxy) === null || _this$_socksProxy2 === void 0 ? void 0 : _this$_socksProxy2.socketFailed(params);
}
async socksData(params) {
var _this$_socksProxy3;
(_this$_socksProxy3 = this._socksProxy) === null || _this$_socksProxy3 === void 0 ? void 0 : _this$_socksProxy3.sendSocketData(params);
}
async socksError(params) {
var _this$_socksProxy4;
(_this$_socksProxy4 = this._socksProxy) === null || _this$_socksProxy4 === void 0 ? void 0 : _this$_socksProxy4.sendSocketError(params);
}
async socksEnd(params) {
var _this$_socksProxy5;
(_this$_socksProxy5 = this._socksProxy) === null || _this$_socksProxy5 === void 0 ? void 0 : _this$_socksProxy5.sendSocketEnd(params);
}
_onDispose() {
_eventsHelper.eventsHelper.removeEventListeners(this._socksListeners);
}
}

View File

@@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.SelectorsDispatcher = void 0;
var _dispatcher = require("./dispatcher");
/**
* 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 SelectorsDispatcher extends _dispatcher.Dispatcher {
constructor(scope, selectors) {
super(scope, selectors, 'Selectors', {});
this._type_Selectors = true;
}
async register(params) {
await this._object.register(params.name, params.source, params.contentScript);
}
async setTestIdAttributeName(params) {
this._object.setTestIdAttributeName(params.testIdAttributeName);
}
}
exports.SelectorsDispatcher = SelectorsDispatcher;

View File

@@ -0,0 +1,58 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.StreamDispatcher = void 0;
var _dispatcher = require("./dispatcher");
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 StreamDispatcher extends _dispatcher.Dispatcher {
constructor(scope, stream) {
super(scope, {
guid: 'stream@' + (0, _utils.createGuid)(),
stream
}, 'Stream', {});
// In Node v12.9.0+ we can use readableEnded.
this._type_Stream = true;
this._ended = false;
stream.once('end', () => this._ended = true);
stream.once('error', () => this._ended = true);
}
async read(params) {
const stream = this._object.stream;
if (this._ended) return {
binary: Buffer.from('')
};
if (!stream.readableLength) {
await new Promise((fulfill, reject) => {
stream.once('readable', fulfill);
stream.once('end', fulfill);
stream.once('error', reject);
});
}
const buffer = stream.read(Math.min(stream.readableLength, params.size || stream.readableLength));
return {
binary: buffer || Buffer.from('')
};
}
async close() {
this._object.stream.destroy();
}
}
exports.StreamDispatcher = StreamDispatcher;

View File

@@ -0,0 +1,54 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.TracingDispatcher = void 0;
var _artifactDispatcher = require("./artifactDispatcher");
var _dispatcher = require("./dispatcher");
/**
* 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 TracingDispatcher extends _dispatcher.Dispatcher {
static from(scope, tracing) {
const result = (0, _dispatcher.existingDispatcher)(tracing);
return result || new TracingDispatcher(scope, tracing);
}
constructor(scope, tracing) {
super(scope, tracing, 'Tracing', {});
this._type_Tracing = true;
}
async tracingStart(params) {
await this._object.start(params);
}
async tracingStartChunk(params) {
return await this._object.startChunk(params);
}
async tracingStopChunk(params) {
const {
artifact,
entries
} = await this._object.stopChunk(params);
return {
artifact: artifact ? _artifactDispatcher.ArtifactDispatcher.from(this, artifact) : undefined,
entries
};
}
async tracingStop(params) {
await this._object.stop();
}
}
exports.TracingDispatcher = TracingDispatcher;

View File

@@ -0,0 +1,49 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.WritableStreamDispatcher = void 0;
var _dispatcher = require("./dispatcher");
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 WritableStreamDispatcher extends _dispatcher.Dispatcher {
constructor(scope, stream) {
super(scope, {
guid: 'writableStream@' + (0, _utils.createGuid)(),
stream
}, 'WritableStream', {});
this._type_WritableStream = true;
}
async write(params) {
const stream = this._object.stream;
await new Promise((fulfill, reject) => {
stream.write(params.binary, error => {
if (error) reject(error);else fulfill();
});
});
}
async close() {
const stream = this._object.stream;
await new Promise(fulfill => stream.end(fulfill));
}
path() {
return this._object.stream.path;
}
}
exports.WritableStreamDispatcher = WritableStreamDispatcher;