chore: remove ExtendedEventEmitter and inline waitForEvent (#2529)
This commit is contained in:
parent
8ee19d53e7
commit
1bb33650b0
|
|
@ -21,12 +21,13 @@ import { Page, PageBinding } from './page';
|
||||||
import { TimeoutSettings } from './timeoutSettings';
|
import { TimeoutSettings } from './timeoutSettings';
|
||||||
import * as types from './types';
|
import * as types from './types';
|
||||||
import { Events } from './events';
|
import { Events } from './events';
|
||||||
import { ExtendedEventEmitter } from './extendedEventEmitter';
|
|
||||||
import { Download } from './download';
|
import { Download } from './download';
|
||||||
import { BrowserBase } from './browser';
|
import { BrowserBase } from './browser';
|
||||||
import { InnerLogger, Logger } from './logger';
|
import { InnerLogger, Logger } from './logger';
|
||||||
import { FunctionWithSource } from './frames';
|
import { FunctionWithSource } from './frames';
|
||||||
import * as debugSupport from './debug/debugSupport';
|
import * as debugSupport from './debug/debugSupport';
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
|
import { ProgressController } from './progress';
|
||||||
|
|
||||||
type CommonContextOptions = {
|
type CommonContextOptions = {
|
||||||
viewport?: types.Size | null,
|
viewport?: types.Size | null,
|
||||||
|
|
@ -76,13 +77,13 @@ export interface BrowserContext {
|
||||||
close(): Promise<void>;
|
close(): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class BrowserContextBase extends ExtendedEventEmitter implements BrowserContext {
|
export abstract class BrowserContextBase extends EventEmitter implements BrowserContext {
|
||||||
readonly _timeoutSettings = new TimeoutSettings();
|
readonly _timeoutSettings = new TimeoutSettings();
|
||||||
readonly _pageBindings = new Map<string, PageBinding>();
|
readonly _pageBindings = new Map<string, PageBinding>();
|
||||||
readonly _options: BrowserContextOptions;
|
readonly _options: BrowserContextOptions;
|
||||||
_routes: { url: types.URLMatch, handler: network.RouteHandler }[] = [];
|
_routes: { url: types.URLMatch, handler: network.RouteHandler }[] = [];
|
||||||
_closed = false;
|
_closed = false;
|
||||||
private readonly _closePromise: Promise<Error>;
|
readonly _closePromise: Promise<Error>;
|
||||||
private _closePromiseFulfill: ((error: Error) => void) | undefined;
|
private _closePromiseFulfill: ((error: Error) => void) | undefined;
|
||||||
readonly _permissions = new Map<string, string[]>();
|
readonly _permissions = new Map<string, string[]>();
|
||||||
readonly _downloads = new Set<Download>();
|
readonly _downloads = new Set<Download>();
|
||||||
|
|
@ -101,16 +102,12 @@ export abstract class BrowserContextBase extends ExtendedEventEmitter implements
|
||||||
await debugSupport.installConsoleHelpers(this);
|
await debugSupport.installConsoleHelpers(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _abortPromiseForEvent(event: string) {
|
async waitForEvent(event: string, optionsOrPredicate: types.WaitForEventOptions = {}): Promise<any> {
|
||||||
return event === Events.BrowserContext.Close ? super._abortPromiseForEvent(event) : this._closePromise;
|
const options = typeof optionsOrPredicate === 'function' ? { predicate: optionsOrPredicate } : optionsOrPredicate;
|
||||||
}
|
const progressController = new ProgressController(this._logger, this._timeoutSettings.timeout(options));
|
||||||
|
if (event !== Events.BrowserContext.Close)
|
||||||
protected _getLogger(): InnerLogger {
|
this._closePromise.then(error => progressController.abort(error));
|
||||||
return this._logger;
|
return progressController.run(progress => helper.waitForEvent(progress, this, event, options.predicate));
|
||||||
}
|
|
||||||
|
|
||||||
protected _getTimeoutSettings(): TimeoutSettings {
|
|
||||||
return this._timeoutSettings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_browserClosed() {
|
_browserClosed() {
|
||||||
|
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { EventEmitter } from 'events';
|
|
||||||
import { helper, RegisteredListener } from './helper';
|
|
||||||
import { ProgressController } from './progress';
|
|
||||||
import { InnerLogger } from './logger';
|
|
||||||
import { TimeoutSettings } from './timeoutSettings';
|
|
||||||
|
|
||||||
export abstract class ExtendedEventEmitter extends EventEmitter {
|
|
||||||
protected _abortPromiseForEvent(event: string) {
|
|
||||||
return new Promise<Error>(() => void 0);
|
|
||||||
}
|
|
||||||
protected abstract _getLogger(): InnerLogger;
|
|
||||||
protected abstract _getTimeoutSettings(): TimeoutSettings;
|
|
||||||
|
|
||||||
async waitForEvent(event: string, optionsOrPredicate: Function | { predicate?: Function, timeout?: number } = {}): Promise<any> {
|
|
||||||
const options = typeof optionsOrPredicate === 'function' ? { predicate: optionsOrPredicate } : optionsOrPredicate;
|
|
||||||
const { predicate = () => true } = options;
|
|
||||||
|
|
||||||
const progressController = new ProgressController(this._getLogger(), this._getTimeoutSettings().timeout(options));
|
|
||||||
this._abortPromiseForEvent(event).then(error => progressController.abort(error));
|
|
||||||
|
|
||||||
return progressController.run(async progress => {
|
|
||||||
const listeners: RegisteredListener[] = [];
|
|
||||||
const promise = new Promise((resolve, reject) => {
|
|
||||||
listeners.push(helper.addEventListener(this, event, eventArg => {
|
|
||||||
try {
|
|
||||||
if (!predicate(eventArg))
|
|
||||||
return;
|
|
||||||
resolve(eventArg);
|
|
||||||
} catch (e) {
|
|
||||||
reject(e);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
progress.cleanupWhenAborted(() => helper.removeEventListeners(listeners));
|
|
||||||
|
|
||||||
const result = await promise;
|
|
||||||
helper.removeEventListeners(listeners);
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -21,6 +21,8 @@ import * as fs from 'fs';
|
||||||
import * as removeFolder from 'rimraf';
|
import * as removeFolder from 'rimraf';
|
||||||
import * as util from 'util';
|
import * as util from 'util';
|
||||||
import * as types from './types';
|
import * as types from './types';
|
||||||
|
import { Progress } from './progress';
|
||||||
|
|
||||||
const removeFolderAsync = util.promisify(removeFolder);
|
const removeFolderAsync = util.promisify(removeFolder);
|
||||||
|
|
||||||
export type RegisteredListener = {
|
export type RegisteredListener = {
|
||||||
|
|
@ -278,6 +280,25 @@ class Helper {
|
||||||
return removeFolderAsync(dir).catch((err: Error) => console.error(err));
|
return removeFolderAsync(dir).catch((err: Error) => console.error(err));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async waitForEvent(progress: Progress, emitter: EventEmitter, event: string, predicate?: Function): Promise<any> {
|
||||||
|
const listeners: RegisteredListener[] = [];
|
||||||
|
const promise = new Promise((resolve, reject) => {
|
||||||
|
listeners.push(helper.addEventListener(emitter, event, eventArg => {
|
||||||
|
try {
|
||||||
|
if (predicate && !predicate(eventArg))
|
||||||
|
return;
|
||||||
|
resolve(eventArg);
|
||||||
|
} catch (e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
progress.cleanupWhenAborted(() => helper.removeEventListeners(listeners));
|
||||||
|
const result = await promise;
|
||||||
|
helper.removeEventListeners(listeners);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assert(value: any, message?: string): asserts value {
|
export function assert(value: any, message?: string): asserts value {
|
||||||
|
|
|
||||||
23
src/page.ts
23
src/page.ts
|
|
@ -28,10 +28,10 @@ import { Events } from './events';
|
||||||
import { BrowserContext, BrowserContextBase } from './browserContext';
|
import { BrowserContext, BrowserContextBase } from './browserContext';
|
||||||
import { ConsoleMessage, ConsoleMessageLocation } from './console';
|
import { ConsoleMessage, ConsoleMessageLocation } from './console';
|
||||||
import * as accessibility from './accessibility';
|
import * as accessibility from './accessibility';
|
||||||
import { ExtendedEventEmitter } from './extendedEventEmitter';
|
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import { FileChooser } from './fileChooser';
|
import { FileChooser } from './fileChooser';
|
||||||
import { logError, InnerLogger } from './logger';
|
import { logError, InnerLogger } from './logger';
|
||||||
|
import { ProgressController } from './progress';
|
||||||
|
|
||||||
export interface PageDelegate {
|
export interface PageDelegate {
|
||||||
readonly rawMouse: input.RawMouse;
|
readonly rawMouse: input.RawMouse;
|
||||||
|
|
@ -88,7 +88,7 @@ type PageState = {
|
||||||
extraHTTPHeaders: network.Headers | null;
|
extraHTTPHeaders: network.Headers | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Page extends ExtendedEventEmitter {
|
export class Page extends EventEmitter {
|
||||||
private _closed = false;
|
private _closed = false;
|
||||||
private _closedCallback: () => void;
|
private _closedCallback: () => void;
|
||||||
private _closedPromise: Promise<void>;
|
private _closedPromise: Promise<void>;
|
||||||
|
|
@ -138,18 +138,6 @@ export class Page extends ExtendedEventEmitter {
|
||||||
this.coverage = delegate.coverage ? delegate.coverage() : null;
|
this.coverage = delegate.coverage ? delegate.coverage() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _abortPromiseForEvent(event: string) {
|
|
||||||
return this._disconnectedPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected _getLogger(): InnerLogger {
|
|
||||||
return this._logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected _getTimeoutSettings(): TimeoutSettings {
|
|
||||||
return this._timeoutSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
_didClose() {
|
_didClose() {
|
||||||
assert(!this._closed, 'Page closed twice');
|
assert(!this._closed, 'Page closed twice');
|
||||||
this._closed = true;
|
this._closed = true;
|
||||||
|
|
@ -337,6 +325,13 @@ export class Page extends ExtendedEventEmitter {
|
||||||
return this.waitForEvent(Events.Page.Response, { predicate, timeout: options.timeout });
|
return this.waitForEvent(Events.Page.Response, { predicate, timeout: options.timeout });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async waitForEvent(event: string, optionsOrPredicate: types.WaitForEventOptions = {}): Promise<any> {
|
||||||
|
const options = typeof optionsOrPredicate === 'function' ? { predicate: optionsOrPredicate } : optionsOrPredicate;
|
||||||
|
const progressController = new ProgressController(this._logger, this._timeoutSettings.timeout(options));
|
||||||
|
this._disconnectedPromise.then(error => progressController.abort(error));
|
||||||
|
return progressController.run(progress => helper.waitForEvent(progress, this, event, options.predicate));
|
||||||
|
}
|
||||||
|
|
||||||
async goBack(options?: types.NavigateOptions): Promise<network.Response | null> {
|
async goBack(options?: types.NavigateOptions): Promise<network.Response | null> {
|
||||||
const waitPromise = this.waitForNavigation(options);
|
const waitPromise = this.waitForNavigation(options);
|
||||||
const result = await this._delegate.goBack();
|
const result = await this._delegate.goBack();
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ import { CRBrowser, CRBrowserContext } from '../chromium/crBrowser';
|
||||||
import { CRConnection, CRSession } from '../chromium/crConnection';
|
import { CRConnection, CRSession } from '../chromium/crConnection';
|
||||||
import { CRExecutionContext } from '../chromium/crExecutionContext';
|
import { CRExecutionContext } from '../chromium/crExecutionContext';
|
||||||
import { Events } from '../events';
|
import { Events } from '../events';
|
||||||
import { ExtendedEventEmitter } from '../extendedEventEmitter';
|
|
||||||
import * as js from '../javascript';
|
import * as js from '../javascript';
|
||||||
import { InnerLogger, Logger } from '../logger';
|
import { InnerLogger, Logger } from '../logger';
|
||||||
import { Page } from '../page';
|
import { Page } from '../page';
|
||||||
|
|
@ -30,7 +29,9 @@ import { BrowserServer } from './browserServer';
|
||||||
import { launchProcess, waitForLine } from './processLauncher';
|
import { launchProcess, waitForLine } from './processLauncher';
|
||||||
import { BrowserContext } from '../browserContext';
|
import { BrowserContext } from '../browserContext';
|
||||||
import type {BrowserWindow} from 'electron';
|
import type {BrowserWindow} from 'electron';
|
||||||
import { runAbortableTask } from '../progress';
|
import { runAbortableTask, ProgressController } from '../progress';
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
|
import { helper } from '../helper';
|
||||||
|
|
||||||
type ElectronLaunchOptions = {
|
type ElectronLaunchOptions = {
|
||||||
args?: string[],
|
args?: string[],
|
||||||
|
|
@ -55,7 +56,7 @@ interface ElectronPage extends Page {
|
||||||
_browserWindowId: number;
|
_browserWindowId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ElectronApplication extends ExtendedEventEmitter {
|
export class ElectronApplication extends EventEmitter {
|
||||||
private _logger: InnerLogger;
|
private _logger: InnerLogger;
|
||||||
private _browserContext: CRBrowserContext;
|
private _browserContext: CRBrowserContext;
|
||||||
private _nodeConnection: CRConnection;
|
private _nodeConnection: CRConnection;
|
||||||
|
|
@ -128,6 +129,14 @@ export class ElectronApplication extends ExtendedEventEmitter {
|
||||||
this._nodeConnection.close();
|
this._nodeConnection.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async waitForEvent(event: string, optionsOrPredicate: types.WaitForEventOptions = {}): Promise<any> {
|
||||||
|
const options = typeof optionsOrPredicate === 'function' ? { predicate: optionsOrPredicate } : optionsOrPredicate;
|
||||||
|
const progressController = new ProgressController(this._logger, this._timeoutSettings.timeout(options));
|
||||||
|
if (event !== ElectronEvents.ElectronApplication.Close)
|
||||||
|
this._browserContext._closePromise.then(error => progressController.abort(error));
|
||||||
|
return progressController.run(progress => helper.waitForEvent(progress, this, event, options.predicate));
|
||||||
|
}
|
||||||
|
|
||||||
async _init() {
|
async _init() {
|
||||||
this._nodeSession.once('Runtime.executionContextCreated', event => {
|
this._nodeSession.once('Runtime.executionContextCreated', event => {
|
||||||
this._nodeExecutionContext = new js.ExecutionContext(new CRExecutionContext(this._nodeSession, event.context));
|
this._nodeExecutionContext = new js.ExecutionContext(new CRExecutionContext(this._nodeSession, event.context));
|
||||||
|
|
@ -152,14 +161,6 @@ export class ElectronApplication extends ExtendedEventEmitter {
|
||||||
async evaluateHandle<R, Arg>(pageFunction: types.FuncOn<any, Arg, R>, arg: Arg): Promise<types.SmartHandle<R>> {
|
async evaluateHandle<R, Arg>(pageFunction: types.FuncOn<any, Arg, R>, arg: Arg): Promise<types.SmartHandle<R>> {
|
||||||
return this._nodeElectronHandle!.evaluateHandle(pageFunction, arg);
|
return this._nodeElectronHandle!.evaluateHandle(pageFunction, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _getLogger(): InnerLogger {
|
|
||||||
return this._logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected _getTimeoutSettings(): TimeoutSettings {
|
|
||||||
return this._timeoutSettings;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Electron {
|
export class Electron {
|
||||||
|
|
|
||||||
|
|
@ -185,4 +185,6 @@ export type ProxySettings = {
|
||||||
bypass?: string,
|
bypass?: string,
|
||||||
username?: string,
|
username?: string,
|
||||||
password?: string
|
password?: string
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export type WaitForEventOptions = Function | { predicate?: Function, timeout?: number };
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue