chore: unify reload/goBack/goForward across browsers (#273)

This commit is contained in:
Dmitry Gozman 2019-12-17 11:28:09 -08:00 committed by GitHub
parent e851a27350
commit 916158656c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 75 deletions

View file

@ -315,32 +315,25 @@ export class FrameManager implements PageDelegate {
return this._networkManager.setCacheEnabled(enabled);
}
async reload(options?: frames.NavigateOptions): Promise<network.Response | null> {
const [response] = await Promise.all([
this._page.waitForNavigation(options),
this._client.send('Page.reload')
]);
return response;
async reload(): Promise<void> {
await this._client.send('Page.reload');
}
private async _go(delta: number, options?: frames.NavigateOptions): Promise<network.Response | null> {
private async _go(delta: number): Promise<boolean> {
const history = await this._client.send('Page.getNavigationHistory');
const entry = history.entries[history.currentIndex + delta];
if (!entry)
return null;
const [response] = await Promise.all([
this._page.waitForNavigation(options),
this._client.send('Page.navigateToHistoryEntry', {entryId: entry.id}),
]);
return response;
return false;
await this._client.send('Page.navigateToHistoryEntry', { entryId: entry.id });
return true;
}
goBack(options?: frames.NavigateOptions): Promise<network.Response | null> {
return this._go(-1, options);
goBack(): Promise<boolean> {
return this._go(-1);
}
goForward(options?: frames.NavigateOptions): Promise<network.Response | null> {
return this._go(+1, options);
goForward(): Promise<boolean> {
return this._go(+1);
}
async evaluateOnNewDocument(source: string): Promise<void> {

View file

@ -223,40 +223,18 @@ export class FrameManager implements PageDelegate {
await this._session.send('Page.setCacheDisabled', {cacheDisabled: !enabled});
}
private async _go(action: () => Promise<{ navigationId: string | null, navigationURL: string | null }>, options: frames.NavigateOptions = {}): Promise<network.Response | null> {
const {
timeout = this._page._timeoutSettings.navigationTimeout(),
waitUntil = (['load'] as frames.LifecycleEvent[]),
} = options;
const frame = this._page.mainFrame();
const watcher = new frames.LifecycleWatcher(frame, waitUntil, timeout);
const { navigationId } = await action();
if (navigationId === null) {
// Cannot go back/forward.
watcher.dispose();
return null;
}
const error = await Promise.race([
watcher.timeoutOrTerminationPromise,
watcher.newDocumentNavigationPromise,
watcher.sameDocumentNavigationPromise,
]);
watcher.dispose();
if (error)
throw error;
return watcher.navigationResponse();
async reload(): Promise<void> {
await this._session.send('Page.reload', { frameId: this._page.mainFrame()._id });
}
reload(options?: frames.NavigateOptions): Promise<network.Response | null> {
return this._go(() => this._session.send('Page.reload', { frameId: this._page.mainFrame()._id }), options);
async goBack(): Promise<boolean> {
const { navigationId } = await this._session.send('Page.goBack', { frameId: this._page.mainFrame()._id });
return navigationId !== null;
}
goBack(options?: frames.NavigateOptions): Promise<network.Response | null> {
return this._go(() => this._session.send('Page.goBack', { frameId: this._page.mainFrame()._id }), options);
}
goForward(options?: frames.NavigateOptions): Promise<network.Response | null> {
return this._go(() => this._session.send('Page.goForward', { frameId: this._page.mainFrame()._id }), options);
async goForward(): Promise<boolean> {
const { navigationId } = await this._session.send('Page.goForward', { frameId: this._page.mainFrame()._id });
return navigationId !== null;
}
async evaluateOnNewDocument(source: string): Promise<void> {

View file

@ -836,7 +836,7 @@ class RerunnableTask {
}
}
export class LifecycleWatcher {
class LifecycleWatcher {
readonly sameDocumentNavigationPromise: Promise<Error | null>;
readonly lifecyclePromise: Promise<void>;
readonly newDocumentNavigationPromise: Promise<Error | null>;

View file

@ -34,9 +34,9 @@ export interface PageDelegate {
readonly rawMouse: input.RawMouse;
readonly rawKeyboard: input.RawKeyboard;
reload(options?: frames.NavigateOptions): Promise<network.Response | null>;
goBack(options?: frames.NavigateOptions): Promise<network.Response | null>;
goForward(options?: frames.NavigateOptions): Promise<network.Response | null>;
reload(): Promise<void>;
goBack(): Promise<boolean>;
goForward(): Promise<boolean>;
exposeBinding(name: string, bindingFunction: string): Promise<void>;
evaluateOnNewDocument(source: string): Promise<void>;
closePage(runBeforeUnload: boolean): Promise<void>;
@ -319,7 +319,9 @@ export class Page extends EventEmitter {
}
async reload(options?: frames.NavigateOptions): Promise<network.Response | null> {
return this._delegate.reload(options);
const waitPromise = this.waitForNavigation(options);
await this._delegate.reload();
return waitPromise;
}
waitForNavigation(options?: frames.NavigateOptions): Promise<network.Response | null> {
@ -353,11 +355,23 @@ export class Page extends EventEmitter {
}
async goBack(options?: frames.NavigateOptions): Promise<network.Response | null> {
return this._delegate.goBack(options);
const waitPromise = this.waitForNavigation(options);
const result = await this._delegate.goBack();
if (!result) {
waitPromise.catch(() => {});
return null;
}
return waitPromise;
}
async goForward(options?: frames.NavigateOptions): Promise<network.Response | null> {
return this._delegate.goForward(options);
const waitPromise = this.waitForNavigation(options);
const result = await this._delegate.goForward();
if (!result) {
waitPromise.catch(() => {});
return null;
}
return waitPromise;
}
async emulate(options: { viewport: types.Viewport; userAgent: string; }) {

View file

@ -282,7 +282,7 @@ export class FrameManager implements PageDelegate {
async setUserAgent(userAgent: string): Promise<void> {
await this._setUserAgent(this._session, userAgent);
await this.reload();
await this._page.reload();
}
async setJavaScriptEnabled(enabled: boolean): Promise<void> {
@ -309,32 +309,24 @@ export class FrameManager implements PageDelegate {
return this._networkManager.setCacheEnabled(enabled);
}
async reload(options?: frames.NavigateOptions): Promise<network.Response | null> {
const [response] = await Promise.all([
this._page.waitForNavigation(options),
this._session.send('Page.reload')
]);
return response;
async reload(): Promise<void> {
await this._session.send('Page.reload');
}
async _go<T extends keyof Protocol.CommandParameters>(command: T, options?: frames.NavigateOptions): Promise<network.Response | null> {
const [response] = await Promise.all([
this._page.waitForNavigation(options),
this._session.send(command).then(() => null),
]).catch(error => {
if (error instanceof Error && error.message.includes(`Protocol error (${command}): Failed to go`))
return [null];
goBack(): Promise<boolean> {
return this._session.send('Page.goBack').then(() => true).catch(error => {
if (error instanceof Error && error.message.includes(`Protocol error (Page.goBack): Failed to go`))
return false;
throw error;
});
return response;
}
goBack(options?: frames.NavigateOptions): Promise<network.Response | null> {
return this._go('Page.goBack', options);
}
goForward(options?: frames.NavigateOptions): Promise<network.Response | null> {
return this._go('Page.goForward', options);
goForward(): Promise<boolean> {
return this._session.send('Page.goForward').then(() => true).catch(error => {
if (error instanceof Error && error.message.includes(`Protocol error (Page.goForward): Failed to go`))
return false;
throw error;
});
}
async exposeBinding(name: string, bindingFunction: string): Promise<void> {