chore: remove ProgressController.abort (#5620)

It is used in a few places, but we can do a Promise.race.
This change will allow us to pass existing progress to
multi-step operations.
This commit is contained in:
Dmitry Gozman 2021-02-25 10:00:54 -08:00 committed by GitHub
parent 2ff6d54f26
commit f7e5db4d6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 39 deletions

View File

@ -100,19 +100,13 @@ export class ElectronApplication extends SdkObject {
} }
async close() { async close() {
const closed = this._waitForEvent(ElectronApplication.Events.Close); const progressController = new ProgressController(internalCallMetadata(), this);
const closed = progressController.run(progress => helper.waitForEvent(progress, this, ElectronApplication.Events.Close).promise, this._timeoutSettings.timeout({}));
await this._nodeElectronHandle!.evaluate(({ app }) => app.quit()); await this._nodeElectronHandle!.evaluate(({ app }) => app.quit());
this._nodeConnection.close(); this._nodeConnection.close();
await closed; await closed;
} }
private async _waitForEvent(event: string, predicate?: Function): Promise<any> {
const progressController = new ProgressController(internalCallMetadata(), this);
if (event !== ElectronApplication.Events.Close)
this._browserContext._closePromise.then(error => progressController.abort(error));
return progressController.run(progress => helper.waitForEvent(progress, this, event, predicate).promise, this._timeoutSettings.timeout({}));
}
async _init() { async _init() {
this._nodeSession.on('Runtime.executionContextCreated', (event: any) => { this._nodeSession.on('Runtime.executionContextCreated', (event: any) => {
if (event.context.auxData && event.context.auxData.isDefault) if (event.context.auxData && event.context.auxData.isDefault)

View File

@ -483,17 +483,22 @@ export class Frame extends SdkObject {
this._subtreeLifecycleEvents = events; this._subtreeLifecycleEvents = events;
} }
setupNavigationProgressController(metadata: CallMetadata): ProgressController { async raceNavigationAction<T>(action: () => Promise<T>): Promise<T> {
const controller = new ProgressController(metadata, this); return Promise.race([
this._page._disconnectedPromise.then(() => controller.abort(new Error('Navigation failed because page was closed!'))); this._page._disconnectedPromise.then(() => { throw new Error('Navigation failed because page was closed!'); }),
this._page._crashedPromise.then(() => controller.abort(new Error('Navigation failed because page crashed!'))); this._page._crashedPromise.then(() => { throw new Error('Navigation failed because page crashed!'); }),
this._detachedPromise.then(() => controller.abort(new Error('Navigating frame was detached!'))); this._detachedPromise.then(() => { throw new Error('Navigating frame was detached!'); }),
return controller; action(),
]);
} }
async goto(metadata: CallMetadata, url: string, options: types.GotoOptions = {}): Promise<network.Response | null> { async goto(metadata: CallMetadata, url: string, options: types.GotoOptions = {}): Promise<network.Response | null> {
const controller = this.setupNavigationProgressController(metadata); const controller = new ProgressController(metadata, this);
return controller.run(async progress => { return controller.run(progress => this._goto(progress, url, options), this._page._timeoutSettings.navigationTimeout(options));
}
private async _goto(progress: Progress, url: string, options: types.GotoOptions): Promise<network.Response | null> {
return this.raceNavigationAction(async () => {
const waitUntil = verifyLifecycle('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil); const waitUntil = verifyLifecycle('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);
progress.log(`navigating to "${url}", waiting until "${waitUntil}"`); progress.log(`navigating to "${url}", waiting until "${waitUntil}"`);
const headers = this._page._state.extraHTTPHeaders || []; const headers = this._page._state.extraHTTPHeaders || [];
@ -536,7 +541,7 @@ export class Frame extends SdkObject {
const response = request ? request._finalRequest().response() : null; const response = request ? request._finalRequest().response() : null;
await this._page._doSlowMo(); await this._page._doSlowMo();
return response; return response;
}, this._page._timeoutSettings.navigationTimeout(options)); });
} }
async _waitForNavigation(progress: Progress, options: types.NavigateOptions): Promise<network.Response | null> { async _waitForNavigation(progress: Progress, options: types.NavigateOptions): Promise<network.Response | null> {
@ -672,8 +677,8 @@ export class Frame extends SdkObject {
} }
async setContent(metadata: CallMetadata, html: string, options: types.NavigateOptions = {}): Promise<void> { async setContent(metadata: CallMetadata, html: string, options: types.NavigateOptions = {}): Promise<void> {
const controller = this.setupNavigationProgressController(metadata); const controller = new ProgressController(metadata, this);
return controller.run(async progress => { return controller.run(progress => this.raceNavigationAction(async () => {
const waitUntil = options.waitUntil === undefined ? 'load' : options.waitUntil; const waitUntil = options.waitUntil === undefined ? 'load' : options.waitUntil;
progress.log(`setting frame content, waiting until "${waitUntil}"`); progress.log(`setting frame content, waiting until "${waitUntil}"`);
const tag = `--playwright--set--content--${this._id}--${++this._setContentCounter}--`; const tag = `--playwright--set--content--${this._id}--${++this._setContentCounter}--`;
@ -694,7 +699,7 @@ export class Frame extends SdkObject {
}, { html, tag }); }, { html, tag });
await Promise.all([contentPromise, lifecyclePromise]); await Promise.all([contentPromise, lifecyclePromise]);
await this._page._doSlowMo(); await this._page._doSlowMo();
}, this._page._timeoutSettings.navigationTimeout(options)); }), this._page._timeoutSettings.navigationTimeout(options));
} }
name(): string { name(): string {

View File

@ -299,23 +299,22 @@ export class Page extends SdkObject {
} }
async reload(metadata: CallMetadata, options: types.NavigateOptions): Promise<network.Response | null> { async reload(metadata: CallMetadata, options: types.NavigateOptions): Promise<network.Response | null> {
const controller = this.mainFrame().setupNavigationProgressController(metadata); const controller = new ProgressController(metadata, this);
const response = await controller.run(async progress => { return controller.run(progress => this.mainFrame().raceNavigationAction(async () => {
// Note: waitForNavigation may fail before we get response to reload(), // Note: waitForNavigation may fail before we get response to reload(),
// so we should await it immediately. // so we should await it immediately.
const [response] = await Promise.all([ const [response] = await Promise.all([
this.mainFrame()._waitForNavigation(progress, options), this.mainFrame()._waitForNavigation(progress, options),
this._delegate.reload(), this._delegate.reload(),
]); ]);
await this._doSlowMo();
return response; return response;
}, this._timeoutSettings.navigationTimeout(options)); }), this._timeoutSettings.navigationTimeout(options));
await this._doSlowMo();
return response;
} }
async goBack(metadata: CallMetadata, options: types.NavigateOptions): Promise<network.Response | null> { async goBack(metadata: CallMetadata, options: types.NavigateOptions): Promise<network.Response | null> {
const controller = this.mainFrame().setupNavigationProgressController(metadata); const controller = new ProgressController(metadata, this);
const response = await controller.run(async progress => { return controller.run(progress => this.mainFrame().raceNavigationAction(async () => {
// Note: waitForNavigation may fail before we get response to goBack, // Note: waitForNavigation may fail before we get response to goBack,
// so we should catch it immediately. // so we should catch it immediately.
let error: Error | undefined; let error: Error | undefined;
@ -329,15 +328,14 @@ export class Page extends SdkObject {
const response = await waitPromise; const response = await waitPromise;
if (error) if (error)
throw error; throw error;
await this._doSlowMo();
return response; return response;
}, this._timeoutSettings.navigationTimeout(options)); }), this._timeoutSettings.navigationTimeout(options));
await this._doSlowMo();
return response;
} }
async goForward(metadata: CallMetadata, options: types.NavigateOptions): Promise<network.Response | null> { async goForward(metadata: CallMetadata, options: types.NavigateOptions): Promise<network.Response | null> {
const controller = this.mainFrame().setupNavigationProgressController(metadata); const controller = new ProgressController(metadata, this);
const response = await controller.run(async progress => { return controller.run(progress => this.mainFrame().raceNavigationAction(async () => {
// Note: waitForNavigation may fail before we get response to goForward, // Note: waitForNavigation may fail before we get response to goForward,
// so we should catch it immediately. // so we should catch it immediately.
let error: Error | undefined; let error: Error | undefined;
@ -351,10 +349,9 @@ export class Page extends SdkObject {
const response = await waitPromise; const response = await waitPromise;
if (error) if (error)
throw error; throw error;
await this._doSlowMo();
return response; return response;
}, this._timeoutSettings.navigationTimeout(options)); }), this._timeoutSettings.navigationTimeout(options));
await this._doSlowMo();
return response;
} }
async emulateMedia(options: { media?: types.MediaType | null, colorScheme?: types.ColorScheme | null }) { async emulateMedia(options: { media?: types.MediaType | null, colorScheme?: types.ColorScheme | null }) {

View File

@ -111,10 +111,6 @@ export class ProgressController {
clearTimeout(timer); clearTimeout(timer);
} }
} }
abort(error: Error) {
this._forceAbort(error);
}
} }
async function runCleanup(cleanup: () => any) { async function runCleanup(cleanup: () => any) {