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); return this._networkManager.setCacheEnabled(enabled);
} }
async reload(options?: frames.NavigateOptions): Promise<network.Response | null> { async reload(): Promise<void> {
const [response] = await Promise.all([ await this._client.send('Page.reload');
this._page.waitForNavigation(options),
this._client.send('Page.reload')
]);
return response;
} }
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 history = await this._client.send('Page.getNavigationHistory');
const entry = history.entries[history.currentIndex + delta]; const entry = history.entries[history.currentIndex + delta];
if (!entry) if (!entry)
return null; return false;
const [response] = await Promise.all([ await this._client.send('Page.navigateToHistoryEntry', { entryId: entry.id });
this._page.waitForNavigation(options), return true;
this._client.send('Page.navigateToHistoryEntry', {entryId: entry.id}),
]);
return response;
} }
goBack(options?: frames.NavigateOptions): Promise<network.Response | null> { goBack(): Promise<boolean> {
return this._go(-1, options); return this._go(-1);
} }
goForward(options?: frames.NavigateOptions): Promise<network.Response | null> { goForward(): Promise<boolean> {
return this._go(+1, options); return this._go(+1);
} }
async evaluateOnNewDocument(source: string): Promise<void> { 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}); 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> { async reload(): Promise<void> {
const { await this._session.send('Page.reload', { frameId: this._page.mainFrame()._id });
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();
} }
reload(options?: frames.NavigateOptions): Promise<network.Response | null> { async goBack(): Promise<boolean> {
return this._go(() => this._session.send('Page.reload', { frameId: this._page.mainFrame()._id }), options); const { navigationId } = await this._session.send('Page.goBack', { frameId: this._page.mainFrame()._id });
return navigationId !== null;
} }
goBack(options?: frames.NavigateOptions): Promise<network.Response | null> { async goForward(): Promise<boolean> {
return this._go(() => this._session.send('Page.goBack', { frameId: this._page.mainFrame()._id }), options); const { navigationId } = await this._session.send('Page.goForward', { frameId: this._page.mainFrame()._id });
} return navigationId !== null;
goForward(options?: frames.NavigateOptions): Promise<network.Response | null> {
return this._go(() => this._session.send('Page.goForward', { frameId: this._page.mainFrame()._id }), options);
} }
async evaluateOnNewDocument(source: string): Promise<void> { 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 sameDocumentNavigationPromise: Promise<Error | null>;
readonly lifecyclePromise: Promise<void>; readonly lifecyclePromise: Promise<void>;
readonly newDocumentNavigationPromise: Promise<Error | null>; readonly newDocumentNavigationPromise: Promise<Error | null>;

View file

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