mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: remove unneeded files, reuse events between browsers, no implicit any (#191)
This commit is contained in:
parent
d96cd76852
commit
f1f9dc166b
@ -1,6 +0,0 @@
|
|||||||
export interface ConnectionTransport {
|
|
||||||
send(s: string): void;
|
|
||||||
close(): void;
|
|
||||||
onmessage?: (message: string) => void,
|
|
||||||
onclose?: () => void,
|
|
||||||
}
|
|
||||||
@ -15,7 +15,15 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const DeviceDescriptors = [
|
import * as types from './types';
|
||||||
|
|
||||||
|
export type DeviceDescriptor = {
|
||||||
|
name: string,
|
||||||
|
userAgent: string,
|
||||||
|
viewport: types.Viewport,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DeviceDescriptors: DeviceDescriptor[] = [
|
||||||
{
|
{
|
||||||
'name': 'Blackberry PlayBook',
|
'name': 'Blackberry PlayBook',
|
||||||
'userAgent': 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+',
|
'userAgent': 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+',
|
||||||
|
|||||||
@ -171,7 +171,7 @@ export class Browser extends EventEmitter {
|
|||||||
const existingTarget = this._allTargets().find(predicate);
|
const existingTarget = this._allTargets().find(predicate);
|
||||||
if (existingTarget)
|
if (existingTarget)
|
||||||
return existingTarget;
|
return existingTarget;
|
||||||
let resolve;
|
let resolve: (target: Target) => void;
|
||||||
const targetPromise = new Promise<Target>(x => resolve = x);
|
const targetPromise = new Promise<Target>(x => resolve = x);
|
||||||
this.chromium.on(Events.Chromium.TargetCreated, check);
|
this.chromium.on(Events.Chromium.TargetCreated, check);
|
||||||
this.chromium.on(Events.Chromium.TargetChanged, check);
|
this.chromium.on(Events.Chromium.TargetChanged, check);
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
import * as debug from 'debug';
|
import * as debug from 'debug';
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import { ConnectionTransport } from '../ConnectionTransport';
|
import { ConnectionTransport } from '../types';
|
||||||
import { assert } from '../helper';
|
import { assert } from '../helper';
|
||||||
import { Protocol } from './protocol';
|
import { Protocol } from './protocol';
|
||||||
|
|
||||||
|
|||||||
@ -28,7 +28,7 @@ import { LifecycleWatcher } from './LifecycleWatcher';
|
|||||||
import { NetworkManager, NetworkManagerEvents } from './NetworkManager';
|
import { NetworkManager, NetworkManagerEvents } from './NetworkManager';
|
||||||
import { Page } from '../page';
|
import { Page } from '../page';
|
||||||
import { Protocol } from './protocol';
|
import { Protocol } from './protocol';
|
||||||
import { Events as CommonEvents } from '../events';
|
import { Events } from '../events';
|
||||||
import { toConsoleMessageLocation, exceptionToError, releaseObject } from './protocolHelper';
|
import { toConsoleMessageLocation, exceptionToError, releaseObject } from './protocolHelper';
|
||||||
import * as dialog from '../dialog';
|
import * as dialog from '../dialog';
|
||||||
import { PageDelegate } from '../page';
|
import { PageDelegate } from '../page';
|
||||||
@ -85,18 +85,18 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
(this._page as any).accessibility = new Accessibility(client);
|
(this._page as any).accessibility = new Accessibility(client);
|
||||||
(this._page as any).coverage = new Coverage(client);
|
(this._page as any).coverage = new Coverage(client);
|
||||||
(this._page as any).pdf = new PDF(client);
|
(this._page as any).pdf = new PDF(client);
|
||||||
(this._page as any).workers = new Workers(client, this._page._addConsoleMessage.bind(this._page), error => this._page.emit(CommonEvents.Page.PageError, error));
|
(this._page as any).workers = new Workers(client, this._page._addConsoleMessage.bind(this._page), error => this._page.emit(Events.Page.PageError, error));
|
||||||
(this._page as any).overrides = new Overrides(client);
|
(this._page as any).overrides = new Overrides(client);
|
||||||
(this._page as any).interception = new Interception(this._networkManager);
|
(this._page as any).interception = new Interception(this._networkManager);
|
||||||
|
|
||||||
this._networkManager.on(NetworkManagerEvents.Request, event => this._page.emit(CommonEvents.Page.Request, event));
|
this._networkManager.on(NetworkManagerEvents.Request, event => this._page.emit(Events.Page.Request, event));
|
||||||
this._networkManager.on(NetworkManagerEvents.Response, event => this._page.emit(CommonEvents.Page.Response, event));
|
this._networkManager.on(NetworkManagerEvents.Response, event => this._page.emit(Events.Page.Response, event));
|
||||||
this._networkManager.on(NetworkManagerEvents.RequestFailed, event => this._page.emit(CommonEvents.Page.RequestFailed, event));
|
this._networkManager.on(NetworkManagerEvents.RequestFailed, event => this._page.emit(Events.Page.RequestFailed, event));
|
||||||
this._networkManager.on(NetworkManagerEvents.RequestFinished, event => this._page.emit(CommonEvents.Page.RequestFinished, event));
|
this._networkManager.on(NetworkManagerEvents.RequestFinished, event => this._page.emit(Events.Page.RequestFinished, event));
|
||||||
|
|
||||||
this._client.on('Inspector.targetCrashed', event => this._onTargetCrashed());
|
this._client.on('Inspector.targetCrashed', event => this._onTargetCrashed());
|
||||||
this._client.on('Log.entryAdded', event => this._onLogEntryAdded(event));
|
this._client.on('Log.entryAdded', event => this._onLogEntryAdded(event));
|
||||||
this._client.on('Page.domContentEventFired', event => this._page.emit(CommonEvents.Page.DOMContentLoaded));
|
this._client.on('Page.domContentEventFired', event => this._page.emit(Events.Page.DOMContentLoaded));
|
||||||
this._client.on('Page.fileChooserOpened', event => this._onFileChooserOpened(event));
|
this._client.on('Page.fileChooserOpened', event => this._onFileChooserOpened(event));
|
||||||
this._client.on('Page.frameAttached', event => this._onFrameAttached(event.frameId, event.parentFrameId));
|
this._client.on('Page.frameAttached', event => this._onFrameAttached(event.frameId, event.parentFrameId));
|
||||||
this._client.on('Page.frameDetached', event => this._onFrameDetached(event.frameId));
|
this._client.on('Page.frameDetached', event => this._onFrameDetached(event.frameId));
|
||||||
@ -104,7 +104,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
this._client.on('Page.frameStoppedLoading', event => this._onFrameStoppedLoading(event.frameId));
|
this._client.on('Page.frameStoppedLoading', event => this._onFrameStoppedLoading(event.frameId));
|
||||||
this._client.on('Page.javascriptDialogOpening', event => this._onDialog(event));
|
this._client.on('Page.javascriptDialogOpening', event => this._onDialog(event));
|
||||||
this._client.on('Page.lifecycleEvent', event => this._onLifecycleEvent(event));
|
this._client.on('Page.lifecycleEvent', event => this._onLifecycleEvent(event));
|
||||||
this._client.on('Page.loadEventFired', event => this._page.emit(CommonEvents.Page.Load));
|
this._client.on('Page.loadEventFired', event => this._page.emit(Events.Page.Load));
|
||||||
this._client.on('Page.navigatedWithinDocument', event => this._onFrameNavigatedWithinDocument(event.frameId, event.url));
|
this._client.on('Page.navigatedWithinDocument', event => this._onFrameNavigatedWithinDocument(event.frameId, event.url));
|
||||||
this._client.on('Runtime.bindingCalled', event => this._onBindingCalled(event));
|
this._client.on('Runtime.bindingCalled', event => this._onBindingCalled(event));
|
||||||
this._client.on('Runtime.consoleAPICalled', event => this._onConsoleAPI(event));
|
this._client.on('Runtime.consoleAPICalled', event => this._onConsoleAPI(event));
|
||||||
@ -280,10 +280,10 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
id: frameId,
|
id: frameId,
|
||||||
loaderId: '',
|
loaderId: '',
|
||||||
};
|
};
|
||||||
frame[frameDataSymbol] = data;
|
(frame as any)[frameDataSymbol] = data;
|
||||||
this._frames.set(frameId, frame);
|
this._frames.set(frameId, frame);
|
||||||
this.emit(FrameManagerEvents.FrameAttached, frame);
|
this.emit(FrameManagerEvents.FrameAttached, frame);
|
||||||
this._page.emit(CommonEvents.Page.FrameAttached, frame);
|
this._page.emit(Events.Page.FrameAttached, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onFrameNavigated(framePayload: Protocol.Page.Frame) {
|
_onFrameNavigated(framePayload: Protocol.Page.Frame) {
|
||||||
@ -311,7 +311,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
id: framePayload.id,
|
id: framePayload.id,
|
||||||
loaderId: '',
|
loaderId: '',
|
||||||
};
|
};
|
||||||
frame[frameDataSymbol] = data;
|
(frame as any)[frameDataSymbol] = data;
|
||||||
}
|
}
|
||||||
this._frames.set(framePayload.id, frame);
|
this._frames.set(framePayload.id, frame);
|
||||||
this._mainFrame = frame;
|
this._mainFrame = frame;
|
||||||
@ -321,7 +321,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
frame._navigated(framePayload.url, framePayload.name);
|
frame._navigated(framePayload.url, framePayload.name);
|
||||||
|
|
||||||
this.emit(FrameManagerEvents.FrameNavigated, frame);
|
this.emit(FrameManagerEvents.FrameNavigated, frame);
|
||||||
this._page.emit(CommonEvents.Page.FrameNavigated, frame);
|
this._page.emit(Events.Page.FrameNavigated, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _ensureIsolatedWorld(name: string) {
|
async _ensureIsolatedWorld(name: string) {
|
||||||
@ -346,7 +346,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
frame._navigated(url, frame.name());
|
frame._navigated(url, frame.name());
|
||||||
this.emit(FrameManagerEvents.FrameNavigatedWithinDocument, frame);
|
this.emit(FrameManagerEvents.FrameNavigatedWithinDocument, frame);
|
||||||
this.emit(FrameManagerEvents.FrameNavigated, frame);
|
this.emit(FrameManagerEvents.FrameNavigated, frame);
|
||||||
this._page.emit(CommonEvents.Page.FrameNavigated, frame);
|
this._page.emit(Events.Page.FrameNavigated, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onFrameDetached(frameId: string) {
|
_onFrameDetached(frameId: string) {
|
||||||
@ -355,16 +355,16 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
this._removeFramesRecursively(frame);
|
this._removeFramesRecursively(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onExecutionContextCreated(contextPayload) {
|
_onExecutionContextCreated(contextPayload: Protocol.Runtime.ExecutionContextDescription) {
|
||||||
const frameId = contextPayload.auxData ? contextPayload.auxData.frameId : null;
|
const frameId = contextPayload.auxData ? contextPayload.auxData.frameId : null;
|
||||||
const frame = this._frames.get(frameId) || null;
|
const frame = this._frames.get(frameId) || null;
|
||||||
if (contextPayload.auxData && contextPayload.auxData['type'] === 'isolated')
|
if (contextPayload.auxData && contextPayload.auxData.type === 'isolated')
|
||||||
this._isolatedWorlds.add(contextPayload.name);
|
this._isolatedWorlds.add(contextPayload.name);
|
||||||
const context = new js.ExecutionContext(new ExecutionContextDelegate(this._client, contextPayload));
|
const context = new js.ExecutionContext(new ExecutionContextDelegate(this._client, contextPayload));
|
||||||
if (frame)
|
if (frame)
|
||||||
context._domWorld = new dom.DOMWorld(context, new DOMWorldDelegate(this, frame));
|
context._domWorld = new dom.DOMWorld(context, new DOMWorldDelegate(this, frame));
|
||||||
if (frame) {
|
if (frame) {
|
||||||
if (contextPayload.auxData && !!contextPayload.auxData['isDefault'])
|
if (contextPayload.auxData && !!contextPayload.auxData.isDefault)
|
||||||
frame._contextCreated('main', context);
|
frame._contextCreated('main', context);
|
||||||
else if (contextPayload.name === UTILITY_WORLD_NAME)
|
else if (contextPayload.name === UTILITY_WORLD_NAME)
|
||||||
frame._contextCreated('utility', context);
|
frame._contextCreated('utility', context);
|
||||||
@ -398,7 +398,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
frame._detach();
|
frame._detach();
|
||||||
this._frames.delete(this._frameData(frame).id);
|
this._frames.delete(this._frameData(frame).id);
|
||||||
this.emit(FrameManagerEvents.FrameDetached, frame);
|
this.emit(FrameManagerEvents.FrameDetached, frame);
|
||||||
this._page.emit(CommonEvents.Page.FrameDetached, frame);
|
this._page.emit(Events.Page.FrameDetached, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onConsoleAPI(event: Protocol.Runtime.consoleAPICalledPayload) {
|
async _onConsoleAPI(event: Protocol.Runtime.consoleAPICalledPayload) {
|
||||||
@ -435,7 +435,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onDialog(event : Protocol.Page.javascriptDialogOpeningPayload) {
|
_onDialog(event : Protocol.Page.javascriptDialogOpeningPayload) {
|
||||||
this._page.emit(CommonEvents.Page.Dialog, new dialog.Dialog(
|
this._page.emit(Events.Page.Dialog, new dialog.Dialog(
|
||||||
event.type as dialog.DialogType,
|
event.type as dialog.DialogType,
|
||||||
event.message,
|
event.message,
|
||||||
async (accept: boolean, promptText?: string) => {
|
async (accept: boolean, promptText?: string) => {
|
||||||
@ -445,7 +445,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
}
|
}
|
||||||
|
|
||||||
_handleException(exceptionDetails: Protocol.Runtime.ExceptionDetails) {
|
_handleException(exceptionDetails: Protocol.Runtime.ExceptionDetails) {
|
||||||
this._page.emit(CommonEvents.Page.PageError, exceptionToError(exceptionDetails));
|
this._page.emit(Events.Page.PageError, exceptionToError(exceptionDetails));
|
||||||
}
|
}
|
||||||
|
|
||||||
_onTargetCrashed() {
|
_onTargetCrashed() {
|
||||||
@ -457,7 +457,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
if (args)
|
if (args)
|
||||||
args.map(arg => releaseObject(this._client, arg));
|
args.map(arg => releaseObject(this._client, arg));
|
||||||
if (source !== 'worker')
|
if (source !== 'worker')
|
||||||
this._page.emit(CommonEvents.Page.Console, new ConsoleMessage(level, text, [], {url, lineNumber}));
|
this._page.emit(Events.Page.Console, new ConsoleMessage(level, text, [], {url, lineNumber}));
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onFileChooserOpened(event: Protocol.Page.fileChooserOpenedPayload) {
|
async _onFileChooserOpened(event: Protocol.Page.fileChooserOpenedPayload) {
|
||||||
@ -550,8 +550,8 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function assertNoLegacyNavigationOptions(options) {
|
function assertNoLegacyNavigationOptions(options: frames.NavigateOptions) {
|
||||||
assert(options['networkIdleTimeout'] === undefined, 'ERROR: networkIdleTimeout option is no longer supported.');
|
assert((options as any)['networkIdleTimeout'] === undefined, 'ERROR: networkIdleTimeout option is no longer supported.');
|
||||||
assert(options['networkIdleInflight'] === undefined, 'ERROR: networkIdleInflight option is no longer supported.');
|
assert((options as any)['networkIdleInflight'] === undefined, 'ERROR: networkIdleInflight option is no longer supported.');
|
||||||
assert(options.waitUntil !== 'networkidle', 'ERROR: "networkidle" option is no longer supported. Use "networkidle2" instead');
|
assert((options as any).waitUntil !== 'networkidle', 'ERROR: "networkidle" option is no longer supported. Use "networkidle2" instead');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,7 +31,7 @@ import { assert, debugError, helper } from '../helper';
|
|||||||
import * as types from '../types';
|
import * as types from '../types';
|
||||||
import { PipeTransport } from './PipeTransport';
|
import { PipeTransport } from './PipeTransport';
|
||||||
import { WebSocketTransport } from './WebSocketTransport';
|
import { WebSocketTransport } from './WebSocketTransport';
|
||||||
import { ConnectionTransport } from '../ConnectionTransport';
|
import { ConnectionTransport } from '../types';
|
||||||
import * as util from 'util';
|
import * as util from 'util';
|
||||||
|
|
||||||
const mkdtempAsync = helper.promisify(fs.mkdtemp);
|
const mkdtempAsync = helper.promisify(fs.mkdtemp);
|
||||||
@ -100,7 +100,7 @@ export class Launcher {
|
|||||||
else
|
else
|
||||||
chromeArguments.push(...args);
|
chromeArguments.push(...args);
|
||||||
|
|
||||||
let temporaryUserDataDir = null;
|
let temporaryUserDataDir: string | null = null;
|
||||||
|
|
||||||
if (!chromeArguments.some(argument => argument.startsWith('--remote-debugging-')))
|
if (!chromeArguments.some(argument => argument.startsWith('--remote-debugging-')))
|
||||||
chromeArguments.push(pipe ? '--remote-debugging-pipe' : '--remote-debugging-port=0');
|
chromeArguments.push(pipe ? '--remote-debugging-pipe' : '--remote-debugging-port=0');
|
||||||
@ -139,7 +139,7 @@ export class Launcher {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!chromeProcess.pid) {
|
if (!chromeProcess.pid) {
|
||||||
let reject;
|
let reject: (e: Error) => void;
|
||||||
const result = new Promise((f, r) => reject = r);
|
const result = new Promise((f, r) => reject = r);
|
||||||
chromeProcess.once('error', error => {
|
chromeProcess.once('error', error => {
|
||||||
reject(new Error('Failed to launch browser: ' + error));
|
reject(new Error('Failed to launch browser: ' + error));
|
||||||
@ -160,7 +160,7 @@ export class Launcher {
|
|||||||
if (temporaryUserDataDir) {
|
if (temporaryUserDataDir) {
|
||||||
removeFolderAsync(temporaryUserDataDir)
|
removeFolderAsync(temporaryUserDataDir)
|
||||||
.then(() => fulfill())
|
.then(() => fulfill())
|
||||||
.catch(err => console.error(err));
|
.catch((err: Error) => console.error(err));
|
||||||
} else {
|
} else {
|
||||||
fulfill();
|
fulfill();
|
||||||
}
|
}
|
||||||
@ -344,7 +344,8 @@ function waitForWSEndpoint(chromeProcess: childProcess.ChildProcess, timeout: nu
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getWSEndpoint(browserURL: string): Promise<string> {
|
function getWSEndpoint(browserURL: string): Promise<string> {
|
||||||
let resolve, reject;
|
let resolve: (url: string) => void;
|
||||||
|
let reject: (e: Error) => void;
|
||||||
const promise = new Promise<string>((res, rej) => { resolve = res; reject = rej; });
|
const promise = new Promise<string>((res, rej) => { resolve = res; reject = rej; });
|
||||||
|
|
||||||
const endpointURL = URL.resolve(browserURL, '/json/version');
|
const endpointURL = URL.resolve(browserURL, '/json/version');
|
||||||
@ -423,7 +424,7 @@ export function createBrowserFetcher(projectRoot: string, options: BrowserFetche
|
|||||||
...defaultOptions,
|
...defaultOptions,
|
||||||
...options,
|
...options,
|
||||||
};
|
};
|
||||||
assert(!!downloadURLs[options.platform], 'Unsupported platform: ' + options.platform);
|
assert(!!(downloadURLs as any)[options.platform], 'Unsupported platform: ' + options.platform);
|
||||||
|
|
||||||
return new BrowserFetcher(options.path, options.platform, (platform: string, revision: string) => {
|
return new BrowserFetcher(options.path, options.platform, (platform: string, revision: string) => {
|
||||||
let archiveName = '';
|
let archiveName = '';
|
||||||
@ -440,7 +441,7 @@ export function createBrowserFetcher(projectRoot: string, options: BrowserFetche
|
|||||||
executablePath = path.join(archiveName, 'chrome.exe');
|
executablePath = path.join(archiveName, 'chrome.exe');
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
downloadUrl: util.format(downloadURLs[platform], options.host, revision, archiveName),
|
downloadUrl: util.format((downloadURLs as any)[platform], options.host, revision, archiveName),
|
||||||
executablePath
|
executablePath
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
import { CDPSessionEvents } from './Connection';
|
import { CDPSessionEvents } from './Connection';
|
||||||
import { TimeoutError } from '../Errors';
|
import { TimeoutError } from '../Errors';
|
||||||
import { FrameManager, FrameManagerEvents } from './FrameManager';
|
import { FrameManager, FrameManagerEvents } from './FrameManager';
|
||||||
import { assert, helper, RegisteredListener } from '../helper';
|
import { helper, RegisteredListener } from '../helper';
|
||||||
import { NetworkManagerEvents } from './NetworkManager';
|
import { NetworkManagerEvents } from './NetworkManager';
|
||||||
import * as frames from '../frames';
|
import * as frames from '../frames';
|
||||||
import * as network from '../network';
|
import * as network from '../network';
|
||||||
|
|||||||
@ -1,93 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2017 Google Inc. All rights reserved.
|
|
||||||
* Modifications copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export class Multimap<T, V> {
|
|
||||||
private _map: Map<T, Set<V>>;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this._map = new Map();
|
|
||||||
}
|
|
||||||
|
|
||||||
set(key: T, value: V) {
|
|
||||||
let set = this._map.get(key);
|
|
||||||
if (!set) {
|
|
||||||
set = new Set();
|
|
||||||
this._map.set(key, set);
|
|
||||||
}
|
|
||||||
set.add(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
get(key: T): Set<V> {
|
|
||||||
let result = this._map.get(key);
|
|
||||||
if (!result)
|
|
||||||
result = new Set();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
has(key: T): boolean {
|
|
||||||
return this._map.has(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
hasValue(key: T, value: V): boolean {
|
|
||||||
const set = this._map.get(key);
|
|
||||||
if (!set)
|
|
||||||
return false;
|
|
||||||
return set.has(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
get size(): number {
|
|
||||||
return this._map.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete(key: T, value: V): boolean {
|
|
||||||
const values = this.get(key);
|
|
||||||
const result = values.delete(value);
|
|
||||||
if (!values.size)
|
|
||||||
this._map.delete(key);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteAll(key: T) {
|
|
||||||
this._map.delete(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
firstValue(key: T): V {
|
|
||||||
const set = this._map.get(key);
|
|
||||||
if (!set)
|
|
||||||
return null;
|
|
||||||
return set.values().next().value;
|
|
||||||
}
|
|
||||||
|
|
||||||
firstKey(): T {
|
|
||||||
return this._map.keys().next().value;
|
|
||||||
}
|
|
||||||
|
|
||||||
valuesArray(): V[] {
|
|
||||||
const result = [];
|
|
||||||
for (const key of this._map.keys())
|
|
||||||
result.push(...Array.from(this._map.get(key).values()));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
keysArray(): T[] {
|
|
||||||
return Array.from(this._map.keys());
|
|
||||||
}
|
|
||||||
|
|
||||||
clear() {
|
|
||||||
this._map.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -337,7 +337,7 @@ class InterceptableRequest {
|
|||||||
await this._client.send('Fetch.fulfillRequest', {
|
await this._client.send('Fetch.fulfillRequest', {
|
||||||
requestId: this._interceptionId,
|
requestId: this._interceptionId,
|
||||||
responseCode: response.status || 200,
|
responseCode: response.status || 200,
|
||||||
responsePhrase: STATUS_TEXTS[response.status || 200],
|
responsePhrase: STATUS_TEXTS[String(response.status || 200)],
|
||||||
responseHeaders: headersArray(responseHeaders),
|
responseHeaders: headersArray(responseHeaders),
|
||||||
body: responseBody ? responseBody.toString('base64') : undefined,
|
body: responseBody ? responseBody.toString('base64') : undefined,
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
@ -367,7 +367,7 @@ class InterceptableRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const errorReasons = {
|
const errorReasons: { [reason: string]: Protocol.Network.ErrorReason } = {
|
||||||
'aborted': 'Aborted',
|
'aborted': 'Aborted',
|
||||||
'accessdenied': 'AccessDenied',
|
'accessdenied': 'AccessDenied',
|
||||||
'addressunreachable': 'AddressUnreachable',
|
'addressunreachable': 'AddressUnreachable',
|
||||||
@ -401,7 +401,7 @@ function headersObject(headers: Protocol.Network.Headers): network.Headers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// List taken from https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml with extra 306 and 418 codes.
|
// List taken from https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml with extra 306 and 418 codes.
|
||||||
const STATUS_TEXTS = {
|
const STATUS_TEXTS: { [status: string]: string } = {
|
||||||
'100': 'Continue',
|
'100': 'Continue',
|
||||||
'101': 'Switching Protocols',
|
'101': 'Switching Protocols',
|
||||||
'102': 'Processing',
|
'102': 'Processing',
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ConnectionTransport } from '../ConnectionTransport';
|
import { ConnectionTransport } from '../types';
|
||||||
import { debugError, helper, RegisteredListener } from '../helper';
|
import { debugError, helper, RegisteredListener } from '../helper';
|
||||||
|
|
||||||
export class PipeTransport implements ConnectionTransport {
|
export class PipeTransport implements ConnectionTransport {
|
||||||
|
|||||||
@ -14,13 +14,16 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Browser } from './Browser';
|
import { Browser } from './Browser';
|
||||||
import { BrowserFetcher, BrowserFetcherOptions, BrowserFetcherRevisionInfo, OnProgressCallback } from '../browserFetcher';
|
import { BrowserFetcher, BrowserFetcherOptions, BrowserFetcherRevisionInfo, OnProgressCallback } from '../browserFetcher';
|
||||||
import { ConnectionTransport } from '../ConnectionTransport';
|
import { ConnectionTransport } from '../types';
|
||||||
import { DeviceDescriptors } from '../DeviceDescriptors';
|
import { DeviceDescriptors, DeviceDescriptor } from '../DeviceDescriptors';
|
||||||
import * as Errors from '../Errors';
|
import * as Errors from '../Errors';
|
||||||
import { Launcher, LauncherBrowserOptions, LauncherChromeArgOptions, LauncherLaunchOptions, createBrowserFetcher } from './Launcher';
|
import { Launcher, LauncherBrowserOptions, LauncherChromeArgOptions, LauncherLaunchOptions, createBrowserFetcher } from './Launcher';
|
||||||
|
|
||||||
|
type Devices = { [name: string]: DeviceDescriptor } & DeviceDescriptor[];
|
||||||
|
|
||||||
export class Playwright {
|
export class Playwright {
|
||||||
private _projectRoot: string;
|
private _projectRoot: string;
|
||||||
private _launcher: Launcher;
|
private _launcher: Launcher;
|
||||||
@ -54,8 +57,8 @@ export class Playwright {
|
|||||||
return this._launcher.executablePath();
|
return this._launcher.executablePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
get devices(): any {
|
get devices(): Devices {
|
||||||
const result = DeviceDescriptors.slice();
|
const result = DeviceDescriptors.slice() as Devices;
|
||||||
for (const device of DeviceDescriptors)
|
for (const device of DeviceDescriptors)
|
||||||
result[device.name] = device;
|
result[device.name] = device;
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import * as types from '../types';
|
|||||||
import { Browser } from './Browser';
|
import { Browser } from './Browser';
|
||||||
import { BrowserContext } from './BrowserContext';
|
import { BrowserContext } from './BrowserContext';
|
||||||
import { CDPSession, CDPSessionEvents } from './Connection';
|
import { CDPSession, CDPSessionEvents } from './Connection';
|
||||||
import { Events as CommonEvents } from '../events';
|
import { Events } from '../events';
|
||||||
import { Worker } from './features/workers';
|
import { Worker } from './features/workers';
|
||||||
import { Page } from '../page';
|
import { Page } from '../page';
|
||||||
import { Protocol } from './protocol';
|
import { Protocol } from './protocol';
|
||||||
@ -65,10 +65,10 @@ export class Target {
|
|||||||
if (!opener || !opener._pagePromise || this.type() !== 'page')
|
if (!opener || !opener._pagePromise || this.type() !== 'page')
|
||||||
return true;
|
return true;
|
||||||
const openerPage = await opener._pagePromise;
|
const openerPage = await opener._pagePromise;
|
||||||
if (!openerPage.listenerCount(CommonEvents.Page.Popup))
|
if (!openerPage.listenerCount(Events.Page.Popup))
|
||||||
return true;
|
return true;
|
||||||
const popupPage = await this.page();
|
const popupPage = await this.page();
|
||||||
openerPage.emit(CommonEvents.Page.Popup, popupPage);
|
openerPage.emit(Events.Page.Popup, popupPage);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
this._isInitialized = this._targetInfo.type !== 'page' || this._targetInfo.url !== '';
|
this._isInitialized = this._targetInfo.type !== 'page' || this._targetInfo.url !== '';
|
||||||
@ -87,7 +87,7 @@ export class Target {
|
|||||||
const frameManager = new FrameManager(client, this._browserContext, this._ignoreHTTPSErrors);
|
const frameManager = new FrameManager(client, this._browserContext, this._ignoreHTTPSErrors);
|
||||||
const page = frameManager.page();
|
const page = frameManager.page();
|
||||||
this._page = page;
|
this._page = page;
|
||||||
page[targetSymbol] = this;
|
(page as any)[targetSymbol] = this;
|
||||||
client.once(CDPSessionEvents.Disconnected, () => page._didDisconnect());
|
client.once(CDPSessionEvents.Disconnected, () => page._didDisconnect());
|
||||||
client.on('Target.attachedToTarget', event => {
|
client.on('Target.attachedToTarget', event => {
|
||||||
if (event.targetInfo.type !== 'worker') {
|
if (event.targetInfo.type !== 'worker') {
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import * as WebSocket from 'ws';
|
import * as WebSocket from 'ws';
|
||||||
import { ConnectionTransport } from '../ConnectionTransport';
|
import { ConnectionTransport } from '../types';
|
||||||
|
|
||||||
export class WebSocketTransport implements ConnectionTransport {
|
export class WebSocketTransport implements ConnectionTransport {
|
||||||
private _ws: WebSocket;
|
private _ws: WebSocket;
|
||||||
|
|||||||
6
src/chromium/tsconfig.json
Normal file
6
src/chromium/tsconfig.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"noImplicitAny": true
|
||||||
|
},
|
||||||
|
"extends": "../../tsconfig.json"
|
||||||
|
}
|
||||||
@ -20,6 +20,7 @@ import { assert, helper, RegisteredListener } from '../helper';
|
|||||||
import { filterCookies, NetworkCookie, SetNetworkCookieParam, rewriteCookies } from '../network';
|
import { filterCookies, NetworkCookie, SetNetworkCookieParam, rewriteCookies } from '../network';
|
||||||
import { Connection, ConnectionEvents, JugglerSessionEvents } from './Connection';
|
import { Connection, ConnectionEvents, JugglerSessionEvents } from './Connection';
|
||||||
import { Events } from './events';
|
import { Events } from './events';
|
||||||
|
import { Events as CommonEvents } from '../events';
|
||||||
import { Permissions } from './features/permissions';
|
import { Permissions } from './features/permissions';
|
||||||
import { Page } from '../page';
|
import { Page } from '../page';
|
||||||
import * as types from '../types';
|
import * as types from '../types';
|
||||||
@ -164,9 +165,9 @@ export class Browser extends EventEmitter {
|
|||||||
this._targets.set(targetId, target);
|
this._targets.set(targetId, target);
|
||||||
if (target.opener() && target.opener()._pagePromise) {
|
if (target.opener() && target.opener()._pagePromise) {
|
||||||
const openerPage = await target.opener()._pagePromise;
|
const openerPage = await target.opener()._pagePromise;
|
||||||
if (openerPage.listenerCount(Events.Page.Popup)) {
|
if (openerPage.listenerCount(CommonEvents.Page.Popup)) {
|
||||||
const popupPage = await target.page();
|
const popupPage = await target.page();
|
||||||
openerPage.emit(Events.Page.Popup, popupPage);
|
openerPage.emit(CommonEvents.Page.Popup, popupPage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
import {assert} from '../helper';
|
import {assert} from '../helper';
|
||||||
import {EventEmitter} from 'events';
|
import {EventEmitter} from 'events';
|
||||||
import * as debug from 'debug';
|
import * as debug from 'debug';
|
||||||
import { ConnectionTransport } from '../ConnectionTransport';
|
import { ConnectionTransport } from '../types';
|
||||||
import { Protocol } from './protocol';
|
import { Protocol } from './protocol';
|
||||||
const debugProtocol = debug('playwright:protocol');
|
const debugProtocol = debug('playwright:protocol');
|
||||||
|
|
||||||
|
|||||||
@ -27,8 +27,7 @@ import { NavigationWatchdog, NextNavigationWatchdog } from './NavigationWatchdog
|
|||||||
import { Page, PageDelegate } from '../page';
|
import { Page, PageDelegate } from '../page';
|
||||||
import { NetworkManager, NetworkManagerEvents } from './NetworkManager';
|
import { NetworkManager, NetworkManagerEvents } from './NetworkManager';
|
||||||
import { DOMWorldDelegate } from './JSHandle';
|
import { DOMWorldDelegate } from './JSHandle';
|
||||||
import { Events } from './events';
|
import { Events } from '../events';
|
||||||
import { Events as CommonEvents } from '../events';
|
|
||||||
import * as dialog from '../dialog';
|
import * as dialog from '../dialog';
|
||||||
import { Protocol } from './protocol';
|
import { Protocol } from './protocol';
|
||||||
import * as input from '../input';
|
import * as input from '../input';
|
||||||
@ -89,10 +88,10 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
helper.addEventListener(this._session, 'Page.dialogOpened', this._onDialogOpened.bind(this)),
|
helper.addEventListener(this._session, 'Page.dialogOpened', this._onDialogOpened.bind(this)),
|
||||||
helper.addEventListener(this._session, 'Page.bindingCalled', this._onBindingCalled.bind(this)),
|
helper.addEventListener(this._session, 'Page.bindingCalled', this._onBindingCalled.bind(this)),
|
||||||
helper.addEventListener(this._session, 'Page.fileChooserOpened', this._onFileChooserOpened.bind(this)),
|
helper.addEventListener(this._session, 'Page.fileChooserOpened', this._onFileChooserOpened.bind(this)),
|
||||||
helper.addEventListener(this._networkManager, NetworkManagerEvents.Request, request => this._page.emit(CommonEvents.Page.Request, request)),
|
helper.addEventListener(this._networkManager, NetworkManagerEvents.Request, request => this._page.emit(Events.Page.Request, request)),
|
||||||
helper.addEventListener(this._networkManager, NetworkManagerEvents.Response, response => this._page.emit(CommonEvents.Page.Response, response)),
|
helper.addEventListener(this._networkManager, NetworkManagerEvents.Response, response => this._page.emit(Events.Page.Response, response)),
|
||||||
helper.addEventListener(this._networkManager, NetworkManagerEvents.RequestFinished, request => this._page.emit(CommonEvents.Page.RequestFinished, request)),
|
helper.addEventListener(this._networkManager, NetworkManagerEvents.RequestFinished, request => this._page.emit(Events.Page.RequestFinished, request)),
|
||||||
helper.addEventListener(this._networkManager, NetworkManagerEvents.RequestFailed, request => this._page.emit(CommonEvents.Page.RequestFailed, request)),
|
helper.addEventListener(this._networkManager, NetworkManagerEvents.RequestFailed, request => this._page.emit(Events.Page.RequestFailed, request)),
|
||||||
];
|
];
|
||||||
this._page = new Page(this, browserContext);
|
this._page = new Page(this, browserContext);
|
||||||
(this._page as any).interception = new Interception(this._networkManager);
|
(this._page as any).interception = new Interception(this._networkManager);
|
||||||
@ -164,14 +163,14 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
data.lastCommittedNavigationId = params.navigationId;
|
data.lastCommittedNavigationId = params.navigationId;
|
||||||
frame._firedLifecycleEvents.clear();
|
frame._firedLifecycleEvents.clear();
|
||||||
this.emit(FrameManagerEvents.FrameNavigated, frame);
|
this.emit(FrameManagerEvents.FrameNavigated, frame);
|
||||||
this._page.emit(CommonEvents.Page.FrameNavigated, frame);
|
this._page.emit(Events.Page.FrameNavigated, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onSameDocumentNavigation(params) {
|
_onSameDocumentNavigation(params) {
|
||||||
const frame = this._frames.get(params.frameId);
|
const frame = this._frames.get(params.frameId);
|
||||||
frame._navigated(params.url, frame.name());
|
frame._navigated(params.url, frame.name());
|
||||||
this.emit(FrameManagerEvents.FrameNavigated, frame);
|
this.emit(FrameManagerEvents.FrameNavigated, frame);
|
||||||
this._page.emit(CommonEvents.Page.FrameNavigated, frame);
|
this._page.emit(Events.Page.FrameNavigated, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onFrameAttached(params) {
|
_onFrameAttached(params) {
|
||||||
@ -188,7 +187,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
}
|
}
|
||||||
this._frames.set(params.frameId, frame);
|
this._frames.set(params.frameId, frame);
|
||||||
this.emit(FrameManagerEvents.FrameAttached, frame);
|
this.emit(FrameManagerEvents.FrameAttached, frame);
|
||||||
this._page.emit(CommonEvents.Page.FrameAttached, frame);
|
this._page.emit(Events.Page.FrameAttached, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onFrameDetached(params) {
|
_onFrameDetached(params) {
|
||||||
@ -196,7 +195,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
this._frames.delete(params.frameId);
|
this._frames.delete(params.frameId);
|
||||||
frame._detach();
|
frame._detach();
|
||||||
this.emit(FrameManagerEvents.FrameDetached, frame);
|
this.emit(FrameManagerEvents.FrameDetached, frame);
|
||||||
this._page.emit(CommonEvents.Page.FrameDetached, frame);
|
this._page.emit(Events.Page.FrameDetached, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onEventFired({frameId, name}) {
|
_onEventFired({frameId, name}) {
|
||||||
@ -205,14 +204,14 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
frame._firedLifecycleEvents.add('load');
|
frame._firedLifecycleEvents.add('load');
|
||||||
if (frame === this._mainFrame) {
|
if (frame === this._mainFrame) {
|
||||||
this.emit(FrameManagerEvents.Load);
|
this.emit(FrameManagerEvents.Load);
|
||||||
this._page.emit(CommonEvents.Page.Load);
|
this._page.emit(Events.Page.Load);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (name === 'DOMContentLoaded') {
|
if (name === 'DOMContentLoaded') {
|
||||||
frame._firedLifecycleEvents.add('domcontentloaded');
|
frame._firedLifecycleEvents.add('domcontentloaded');
|
||||||
if (frame === this._mainFrame) {
|
if (frame === this._mainFrame) {
|
||||||
this.emit(FrameManagerEvents.DOMContentLoaded);
|
this.emit(FrameManagerEvents.DOMContentLoaded);
|
||||||
this._page.emit(CommonEvents.Page.DOMContentLoaded);
|
this._page.emit(Events.Page.DOMContentLoaded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,11 +16,13 @@
|
|||||||
*/
|
*/
|
||||||
import { Browser } from './Browser';
|
import { Browser } from './Browser';
|
||||||
import { BrowserFetcher, BrowserFetcherOptions, OnProgressCallback, BrowserFetcherRevisionInfo } from '../browserFetcher';
|
import { BrowserFetcher, BrowserFetcherOptions, OnProgressCallback, BrowserFetcherRevisionInfo } from '../browserFetcher';
|
||||||
import { ConnectionTransport } from '../ConnectionTransport';
|
import { ConnectionTransport } from '../types';
|
||||||
import { DeviceDescriptors } from '../DeviceDescriptors';
|
import { DeviceDescriptors, DeviceDescriptor } from '../DeviceDescriptors';
|
||||||
import * as Errors from '../Errors';
|
import * as Errors from '../Errors';
|
||||||
import { Launcher, createBrowserFetcher } from './Launcher';
|
import { Launcher, createBrowserFetcher } from './Launcher';
|
||||||
|
|
||||||
|
type Devices = { [name: string]: DeviceDescriptor } & DeviceDescriptor[];
|
||||||
|
|
||||||
export class Playwright {
|
export class Playwright {
|
||||||
private _projectRoot: string;
|
private _projectRoot: string;
|
||||||
private _launcher: Launcher;
|
private _launcher: Launcher;
|
||||||
@ -54,8 +56,8 @@ export class Playwright {
|
|||||||
return this._launcher.executablePath();
|
return this._launcher.executablePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
get devices(): any {
|
get devices(): Devices {
|
||||||
const result = DeviceDescriptors.slice();
|
const result = DeviceDescriptors.slice() as Devices;
|
||||||
for (const device of DeviceDescriptors)
|
for (const device of DeviceDescriptors)
|
||||||
result[device.name] = device;
|
result[device.name] = device;
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { ConnectionTransport } from '../ConnectionTransport';
|
import { ConnectionTransport } from '../types';
|
||||||
import * as WebSocket from 'ws';
|
import * as WebSocket from 'ws';
|
||||||
|
|
||||||
export class WebSocketTransport implements ConnectionTransport {
|
export class WebSocketTransport implements ConnectionTransport {
|
||||||
|
|||||||
@ -16,26 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export const Events = {
|
export const Events = {
|
||||||
Page: {
|
|
||||||
Close: 'close',
|
|
||||||
Console: 'console',
|
|
||||||
Dialog: 'dialog',
|
|
||||||
FileChooser: 'filechooser',
|
|
||||||
DOMContentLoaded: 'domcontentloaded',
|
|
||||||
// Can't use just 'error' due to node.js special treatment of error events.
|
|
||||||
// @see https://nodejs.org/api/events.html#events_error_events
|
|
||||||
PageError: 'pageerror',
|
|
||||||
Request: 'request',
|
|
||||||
Response: 'response',
|
|
||||||
RequestFailed: 'requestfailed',
|
|
||||||
RequestFinished: 'requestfinished',
|
|
||||||
FrameAttached: 'frameattached',
|
|
||||||
FrameDetached: 'framedetached',
|
|
||||||
FrameNavigated: 'framenavigated',
|
|
||||||
Load: 'load',
|
|
||||||
Popup: 'popup',
|
|
||||||
},
|
|
||||||
|
|
||||||
Browser: {
|
Browser: {
|
||||||
Disconnected: 'disconnected'
|
Disconnected: 'disconnected'
|
||||||
},
|
},
|
||||||
|
|||||||
@ -19,7 +19,7 @@ class Injected {
|
|||||||
|
|
||||||
querySelector(selector: string, root: Node): Element | undefined {
|
querySelector(selector: string, root: Node): Element | undefined {
|
||||||
const parsed = this._parseSelector(selector);
|
const parsed = this._parseSelector(selector);
|
||||||
if (!root['querySelector'])
|
if (!(root as any)['querySelector'])
|
||||||
throw new Error('Node is not queryable.');
|
throw new Error('Node is not queryable.');
|
||||||
let element = root as SelectorRoot;
|
let element = root as SelectorRoot;
|
||||||
for (const { engine, selector } of parsed) {
|
for (const { engine, selector } of parsed) {
|
||||||
@ -33,7 +33,7 @@ class Injected {
|
|||||||
|
|
||||||
querySelectorAll(selector: string, root: Node): Element[] {
|
querySelectorAll(selector: string, root: Node): Element[] {
|
||||||
const parsed = this._parseSelector(selector);
|
const parsed = this._parseSelector(selector);
|
||||||
if (!root['querySelectorAll'])
|
if (!(root as any)['querySelectorAll'])
|
||||||
throw new Error('Node is not queryable.');
|
throw new Error('Node is not queryable.');
|
||||||
let set = new Set<SelectorRoot>([ root as SelectorRoot ]);
|
let set = new Set<SelectorRoot>([ root as SelectorRoot ]);
|
||||||
for (const { engine, selector } of parsed) {
|
for (const { engine, selector } of parsed) {
|
||||||
@ -105,7 +105,7 @@ class Injected {
|
|||||||
if (success)
|
if (success)
|
||||||
return Promise.resolve(success);
|
return Promise.resolve(success);
|
||||||
|
|
||||||
let fulfill;
|
let fulfill: (result?: any) => void;
|
||||||
const result = new Promise(x => fulfill = x);
|
const result = new Promise(x => fulfill = x);
|
||||||
const observer = new MutationObserver(mutations => {
|
const observer = new MutationObserver(mutations => {
|
||||||
if (timedOut) {
|
if (timedOut) {
|
||||||
@ -131,7 +131,7 @@ class Injected {
|
|||||||
if (timeout)
|
if (timeout)
|
||||||
setTimeout(() => timedOut = true, timeout);
|
setTimeout(() => timedOut = true, timeout);
|
||||||
|
|
||||||
let fulfill;
|
let fulfill: (result?: any) => void;
|
||||||
const result = new Promise(x => fulfill = x);
|
const result = new Promise(x => fulfill = x);
|
||||||
onRaf();
|
onRaf();
|
||||||
return result;
|
return result;
|
||||||
@ -154,7 +154,7 @@ class Injected {
|
|||||||
if (timeout)
|
if (timeout)
|
||||||
setTimeout(() => timedOut = true, timeout);
|
setTimeout(() => timedOut = true, timeout);
|
||||||
|
|
||||||
let fulfill;
|
let fulfill: (result?: any) => void;
|
||||||
const result = new Promise(x => fulfill = x);
|
const result = new Promise(x => fulfill = x);
|
||||||
onTimeout();
|
onTimeout();
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
6
src/injected/tsconfig.json
Normal file
6
src/injected/tsconfig.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"noImplicitAny": true
|
||||||
|
},
|
||||||
|
"extends": "../../tsconfig.json"
|
||||||
|
}
|
||||||
@ -62,4 +62,11 @@ export type Viewport = {
|
|||||||
isMobile?: boolean;
|
isMobile?: boolean;
|
||||||
isLandscape?: boolean;
|
isLandscape?: boolean;
|
||||||
hasTouch?: boolean;
|
hasTouch?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface ConnectionTransport {
|
||||||
|
send(s: string): void;
|
||||||
|
close(): void;
|
||||||
|
onmessage?: (message: string) => void,
|
||||||
|
onclose?: () => void,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
import {assert} from '../helper';
|
import {assert} from '../helper';
|
||||||
import * as debug from 'debug';
|
import * as debug from 'debug';
|
||||||
import {EventEmitter} from 'events';
|
import {EventEmitter} from 'events';
|
||||||
import { ConnectionTransport } from '../ConnectionTransport';
|
import { ConnectionTransport } from '../types';
|
||||||
import { Protocol } from './protocol';
|
import { Protocol } from './protocol';
|
||||||
|
|
||||||
const debugProtocol = debug('playwright:protocol');
|
const debugProtocol = debug('playwright:protocol');
|
||||||
|
|||||||
@ -23,8 +23,7 @@ import * as js from '../javascript';
|
|||||||
import * as dom from '../dom';
|
import * as dom from '../dom';
|
||||||
import * as network from '../network';
|
import * as network from '../network';
|
||||||
import { TargetSession, TargetSessionEvents } from './Connection';
|
import { TargetSession, TargetSessionEvents } from './Connection';
|
||||||
import { Events } from './events';
|
import { Events } from '../events';
|
||||||
import { Events as CommonEvents } from '../events';
|
|
||||||
import { ExecutionContextDelegate, EVALUATION_SCRIPT_URL } from './ExecutionContext';
|
import { ExecutionContextDelegate, EVALUATION_SCRIPT_URL } from './ExecutionContext';
|
||||||
import { NetworkManager, NetworkManagerEvents } from './NetworkManager';
|
import { NetworkManager, NetworkManagerEvents } from './NetworkManager';
|
||||||
import { Page, PageDelegate } from '../page';
|
import { Page, PageDelegate } from '../page';
|
||||||
@ -78,10 +77,10 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
this._contextIdToContext = new Map();
|
this._contextIdToContext = new Map();
|
||||||
this._isolatedWorlds = new Set();
|
this._isolatedWorlds = new Set();
|
||||||
this._page = new Page(this, browserContext);
|
this._page = new Page(this, browserContext);
|
||||||
this._networkManager.on(NetworkManagerEvents.Request, event => this._page.emit(CommonEvents.Page.Request, event));
|
this._networkManager.on(NetworkManagerEvents.Request, event => this._page.emit(Events.Page.Request, event));
|
||||||
this._networkManager.on(NetworkManagerEvents.Response, event => this._page.emit(CommonEvents.Page.Response, event));
|
this._networkManager.on(NetworkManagerEvents.Response, event => this._page.emit(Events.Page.Response, event));
|
||||||
this._networkManager.on(NetworkManagerEvents.RequestFailed, event => this._page.emit(CommonEvents.Page.RequestFailed, event));
|
this._networkManager.on(NetworkManagerEvents.RequestFailed, event => this._page.emit(Events.Page.RequestFailed, event));
|
||||||
this._networkManager.on(NetworkManagerEvents.RequestFinished, event => this._page.emit(CommonEvents.Page.RequestFinished, event));
|
this._networkManager.on(NetworkManagerEvents.RequestFinished, event => this._page.emit(Events.Page.RequestFinished, event));
|
||||||
}
|
}
|
||||||
|
|
||||||
async initialize(session: TargetSession) {
|
async initialize(session: TargetSession) {
|
||||||
@ -128,9 +127,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
helper.addEventListener(this._session, 'Page.loadEventFired', event => this._onLifecycleEvent(event.frameId, 'load')),
|
helper.addEventListener(this._session, 'Page.loadEventFired', event => this._onLifecycleEvent(event.frameId, 'load')),
|
||||||
helper.addEventListener(this._session, 'Page.domContentEventFired', event => this._onLifecycleEvent(event.frameId, 'domcontentloaded')),
|
helper.addEventListener(this._session, 'Page.domContentEventFired', event => this._onLifecycleEvent(event.frameId, 'domcontentloaded')),
|
||||||
helper.addEventListener(this._session, 'Runtime.executionContextCreated', event => this._onExecutionContextCreated(event.context)),
|
helper.addEventListener(this._session, 'Runtime.executionContextCreated', event => this._onExecutionContextCreated(event.context)),
|
||||||
helper.addEventListener(this._session, 'Page.loadEventFired', event => this._page.emit(Events.Page.Load)),
|
|
||||||
helper.addEventListener(this._session, 'Console.messageAdded', event => this._onConsoleMessage(event)),
|
helper.addEventListener(this._session, 'Console.messageAdded', event => this._onConsoleMessage(event)),
|
||||||
helper.addEventListener(this._session, 'Page.domContentEventFired', event => this._page.emit(Events.Page.DOMContentLoaded)),
|
|
||||||
helper.addEventListener(this._session, 'Dialog.javascriptDialogOpening', event => this._onDialog(event)),
|
helper.addEventListener(this._session, 'Dialog.javascriptDialogOpening', event => this._onDialog(event)),
|
||||||
helper.addEventListener(this._session, 'Page.fileChooserOpened', event => this._onFileChooserOpened(event))
|
helper.addEventListener(this._session, 'Page.fileChooserOpened', event => this._onFileChooserOpened(event))
|
||||||
];
|
];
|
||||||
@ -158,9 +155,9 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
frame._firedLifecycleEvents.add('load');
|
frame._firedLifecycleEvents.add('load');
|
||||||
this.emit(FrameManagerEvents.LifecycleEvent, frame);
|
this.emit(FrameManagerEvents.LifecycleEvent, frame);
|
||||||
if (frame === this.mainFrame() && !hasDOMContentLoaded)
|
if (frame === this.mainFrame() && !hasDOMContentLoaded)
|
||||||
this._page.emit(CommonEvents.Page.DOMContentLoaded);
|
this._page.emit(Events.Page.DOMContentLoaded);
|
||||||
if (frame === this.mainFrame() && !hasLoad)
|
if (frame === this.mainFrame() && !hasLoad)
|
||||||
this._page.emit(CommonEvents.Page.Load);
|
this._page.emit(Events.Page.Load);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onLifecycleEvent(frameId: string, event: frames.LifecycleEvent) {
|
_onLifecycleEvent(frameId: string, event: frames.LifecycleEvent) {
|
||||||
@ -171,9 +168,9 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
this.emit(FrameManagerEvents.LifecycleEvent, frame);
|
this.emit(FrameManagerEvents.LifecycleEvent, frame);
|
||||||
if (frame === this.mainFrame()) {
|
if (frame === this.mainFrame()) {
|
||||||
if (event === 'load')
|
if (event === 'load')
|
||||||
this._page.emit(CommonEvents.Page.Load);
|
this._page.emit(Events.Page.Load);
|
||||||
if (event === 'domcontentloaded')
|
if (event === 'domcontentloaded')
|
||||||
this._page.emit(CommonEvents.Page.DOMContentLoaded);
|
this._page.emit(Events.Page.DOMContentLoaded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +218,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
frame[frameDataSymbol] = data;
|
frame[frameDataSymbol] = data;
|
||||||
this._frames.set(frameId, frame);
|
this._frames.set(frameId, frame);
|
||||||
this.emit(FrameManagerEvents.FrameAttached, frame);
|
this.emit(FrameManagerEvents.FrameAttached, frame);
|
||||||
this._page.emit(CommonEvents.Page.FrameAttached, frame);
|
this._page.emit(Events.Page.FrameAttached, frame);
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,7 +270,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.emit(FrameManagerEvents.FrameNavigated, frame);
|
this.emit(FrameManagerEvents.FrameNavigated, frame);
|
||||||
this._page.emit(CommonEvents.Page.FrameNavigated, frame);
|
this._page.emit(Events.Page.FrameNavigated, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onFrameNavigatedWithinDocument(frameId: string, url: string) {
|
_onFrameNavigatedWithinDocument(frameId: string, url: string) {
|
||||||
@ -283,7 +280,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
frame._navigated(url, frame.name());
|
frame._navigated(url, frame.name());
|
||||||
this.emit(FrameManagerEvents.FrameNavigatedWithinDocument, frame);
|
this.emit(FrameManagerEvents.FrameNavigatedWithinDocument, frame);
|
||||||
this.emit(FrameManagerEvents.FrameNavigated, frame);
|
this.emit(FrameManagerEvents.FrameNavigated, frame);
|
||||||
this._page.emit(CommonEvents.Page.FrameNavigated, frame);
|
this._page.emit(Events.Page.FrameNavigated, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onFrameDetached(frameId: string) {
|
_onFrameDetached(frameId: string) {
|
||||||
@ -324,7 +321,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
|||||||
frame._detach();
|
frame._detach();
|
||||||
this._frames.delete(this._frameData(frame).id);
|
this._frames.delete(this._frameData(frame).id);
|
||||||
this.emit(FrameManagerEvents.FrameDetached, frame);
|
this.emit(FrameManagerEvents.FrameDetached, frame);
|
||||||
this._page.emit(CommonEvents.Page.FrameDetached, frame);
|
this._page.emit(Events.Page.FrameDetached, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
async navigateFrame(frame: frames.Frame, url: string, options: frames.GotoOptions = {}): Promise<network.Response | null> {
|
async navigateFrame(frame: frames.Frame, url: string, options: frames.GotoOptions = {}): Promise<network.Response | null> {
|
||||||
|
|||||||
@ -1,93 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2017 Google Inc. All rights reserved.
|
|
||||||
* Modifications copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export class Multimap<T, V> {
|
|
||||||
private _map: Map<T, Set<V>>;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this._map = new Map();
|
|
||||||
}
|
|
||||||
|
|
||||||
set(key: T, value: V) {
|
|
||||||
let set = this._map.get(key);
|
|
||||||
if (!set) {
|
|
||||||
set = new Set();
|
|
||||||
this._map.set(key, set);
|
|
||||||
}
|
|
||||||
set.add(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
get(key: T): Set<V> {
|
|
||||||
let result = this._map.get(key);
|
|
||||||
if (!result)
|
|
||||||
result = new Set();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
has(key: T): boolean {
|
|
||||||
return this._map.has(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
hasValue(key: T, value: V): boolean {
|
|
||||||
const set = this._map.get(key);
|
|
||||||
if (!set)
|
|
||||||
return false;
|
|
||||||
return set.has(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
get size(): number {
|
|
||||||
return this._map.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete(key: T, value: V): boolean {
|
|
||||||
const values = this.get(key);
|
|
||||||
const result = values.delete(value);
|
|
||||||
if (!values.size)
|
|
||||||
this._map.delete(key);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteAll(key: T) {
|
|
||||||
this._map.delete(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
firstValue(key: T): V {
|
|
||||||
const set = this._map.get(key);
|
|
||||||
if (!set)
|
|
||||||
return null;
|
|
||||||
return set.values().next().value;
|
|
||||||
}
|
|
||||||
|
|
||||||
firstKey(): T {
|
|
||||||
return this._map.keys().next().value;
|
|
||||||
}
|
|
||||||
|
|
||||||
valuesArray(): V[] {
|
|
||||||
const result = [];
|
|
||||||
for (const key of this._map.keys())
|
|
||||||
result.push(...Array.from(this._map.get(key).values()));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
keysArray(): T[] {
|
|
||||||
return Array.from(this._map.keys());
|
|
||||||
}
|
|
||||||
|
|
||||||
clear() {
|
|
||||||
this._map.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ConnectionTransport } from '../ConnectionTransport';
|
import { ConnectionTransport } from '../types';
|
||||||
import { debugError, helper, RegisteredListener } from '../helper';
|
import { debugError, helper, RegisteredListener } from '../helper';
|
||||||
|
|
||||||
export class PipeTransport implements ConnectionTransport {
|
export class PipeTransport implements ConnectionTransport {
|
||||||
|
|||||||
@ -16,22 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export const Events = {
|
export const Events = {
|
||||||
Page: {
|
|
||||||
Close: 'close',
|
|
||||||
Console: 'console',
|
|
||||||
Dialog: 'dialog',
|
|
||||||
FileChooser: 'filechooser',
|
|
||||||
DOMContentLoaded: 'domcontentloaded',
|
|
||||||
Request: 'request',
|
|
||||||
Response: 'response',
|
|
||||||
RequestFailed: 'requestfailed',
|
|
||||||
RequestFinished: 'requestfinished',
|
|
||||||
FrameAttached: 'frameattached',
|
|
||||||
FrameDetached: 'framedetached',
|
|
||||||
FrameNavigated: 'framenavigated',
|
|
||||||
Load: 'load',
|
|
||||||
},
|
|
||||||
|
|
||||||
Browser: {
|
Browser: {
|
||||||
Disconnected: 'disconnected'
|
Disconnected: 'disconnected'
|
||||||
},
|
},
|
||||||
|
|||||||
@ -117,7 +117,7 @@ function checkSources(sources) {
|
|||||||
function serializeSymbol(symbol, circular = []) {
|
function serializeSymbol(symbol, circular = []) {
|
||||||
const type = checker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration);
|
const type = checker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration);
|
||||||
const name = symbol.getName();
|
const name = symbol.getName();
|
||||||
if (symbol.valueDeclaration.dotDotDotToken) {
|
if (symbol.valueDeclaration && symbol.valueDeclaration.dotDotDotToken) {
|
||||||
const innerType = serializeType(type.typeArguments ? type.typeArguments[0] : type, circular);
|
const innerType = serializeType(type.typeArguments ? type.typeArguments[0] : type, circular);
|
||||||
innerType.name = '...' + innerType.name;
|
innerType.name = '...' + innerType.name;
|
||||||
return Documentation.Member.createProperty('...' + name, innerType);
|
return Documentation.Member.createProperty('...' + name, innerType);
|
||||||
|
|||||||
@ -113,6 +113,8 @@ function typeOfProperty(property, domain) {
|
|||||||
return typeOfProperty(property.items, domain) + '[]';
|
return typeOfProperty(property.items, domain) + '[]';
|
||||||
case 'integer':
|
case 'integer':
|
||||||
return 'number';
|
return 'number';
|
||||||
|
case 'object':
|
||||||
|
return '{ [key: string]: string }';
|
||||||
}
|
}
|
||||||
return property.type;
|
return property.type;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user