Skip to content

Commit c1ef683

Browse files
authored
api: remove waitForLoadState() in favor of PageEvent.page(options) (#1323)
1 parent 9b8f4a2 commit c1ef683

11 files changed

+149
-99
lines changed

docs/api.md

+23-46
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,6 @@ This setting will change the default maximum navigation time for the following m
525525
- [page.goto(url[, options])](#pagegotourl-options)
526526
- [page.reload([options])](#pagereloadoptions)
527527
- [page.setContent(html[, options])](#pagesetcontenthtml-options)
528-
- [page.waitForLoadState([options])](#pagewaitforloadstateoptions)
529528
- [page.waitForNavigation([options])](#pagewaitfornavigationoptions)
530529

531530
> **NOTE** [`page.setDefaultNavigationTimeout`](#pagesetdefaultnavigationtimeouttimeout) and [`page.setDefaultTimeout`](#pagesetdefaulttimeouttimeout) take priority over [`browserContext.setDefaultNavigationTimeout`](#browsercontextsetdefaultnavigationtimeouttimeout).
@@ -717,7 +716,6 @@ page.removeListener('request', logRequest);
717716
- [page.waitFor(selectorOrFunctionOrTimeout[, options[, ...args]])](#pagewaitforselectororfunctionortimeout-options-args)
718717
- [page.waitForEvent(event[, optionsOrPredicate])](#pagewaitforeventevent-optionsorpredicate)
719718
- [page.waitForFunction(pageFunction[, options[, ...args]])](#pagewaitforfunctionpagefunction-options-args)
720-
- [page.waitForLoadState([options])](#pagewaitforloadstateoptions)
721719
- [page.waitForNavigation([options])](#pagewaitfornavigationoptions)
722720
- [page.waitForRequest(urlOrPredicate[, options])](#pagewaitforrequesturlorpredicate-options)
723721
- [page.waitForResponse(urlOrPredicate[, options])](#pagewaitforresponseurlorpredicate-options)
@@ -1567,7 +1565,6 @@ This setting will change the default maximum navigation time for the following m
15671565
- [page.goto(url[, options])](#pagegotourl-options)
15681566
- [page.reload([options])](#pagereloadoptions)
15691567
- [page.setContent(html[, options])](#pagesetcontenthtml-options)
1570-
- [page.waitForLoadState([options])](#pagewaitforloadstateoptions)
15711568
- [page.waitForNavigation([options])](#pagewaitfornavigationoptions)
15721569

15731570
> **NOTE** [`page.setDefaultNavigationTimeout`](#pagesetdefaultnavigationtimeouttimeout) takes priority over [`page.setDefaultTimeout`](#pagesetdefaulttimeouttimeout), [`browserContext.setDefaultTimeout`](#browsercontextsetdefaulttimeouttimeout) and [`browserContext.setDefaultNavigationTimeout`](#browsercontextsetdefaultnavigationtimeouttimeout).
@@ -1782,27 +1779,6 @@ await page.waitForFunction(selector => !!document.querySelector(selector), {}, s
17821779

17831780
Shortcut for [page.mainFrame().waitForFunction(pageFunction[, options[, ...args]])](#framewaitforfunctionpagefunction-options-args).
17841781

1785-
#### page.waitForLoadState([options])
1786-
- `options` <[Object]> Navigation parameters which might have the following properties:
1787-
- `timeout` <[number]> Maximum navigation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by using the [browserContext.setDefaultNavigationTimeout(timeout)](#browsercontextsetdefaultnavigationtimeouttimeout), [browserContext.setDefaultTimeout(timeout)](#browsercontextsetdefaulttimeouttimeout), [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout) or [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout) methods.
1788-
- `waitUntil` <"commit"|"load"|"domcontentloaded"|"networkidle0"|"networkidle2"> When to consider navigation succeeded, defaults to `load`. Events can be either:
1789-
- `'commit'` - navigation is committed, new url is displayed in the browser address bar.
1790-
- `'load'` - consider navigation to be finished when the `load` event is fired.
1791-
- `'domcontentloaded'` - consider navigation to be finished when the `DOMContentLoaded` event is fired.
1792-
- `'networkidle0'` - consider navigation to be finished when there are no more than 0 network connections for at least `500` ms.
1793-
- `'networkidle2'` - consider navigation to be finished when there are no more than 2 network connections for at least `500` ms.
1794-
- returns: <[Promise]> Promise which resolves when the load state has been achieved.
1795-
1796-
This resolves when the page reaches a required load state, `load` by default. The navigation can be in progress when it is called.
1797-
If navigation is already at a required state, resolves immediately.
1798-
1799-
```js
1800-
await page.click('button'); // Click triggers navigation.
1801-
await page.waitForLoadState(); // The promise resolves after navigation has finished.
1802-
```
1803-
1804-
Shortcut for [page.mainFrame().waitForLoadState([options])](#framewaitforloadstateoptions).
1805-
18061782
#### page.waitForNavigation([options])
18071783
- `options` <[Object]> Navigation parameters which might have the following properties:
18081784
- `timeout` <[number]> Maximum navigation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by using the [browserContext.setDefaultNavigationTimeout(timeout)](#browsercontextsetdefaultnavigationtimeouttimeout), [browserContext.setDefaultTimeout(timeout)](#browsercontextsetdefaulttimeouttimeout), [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout) or [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout) methods.
@@ -1895,8 +1871,29 @@ This method returns all of the dedicated [WebWorkers](https://developer.mozilla.
18951871

18961872
Event object passed to the listeners of [`browserContext.on('page')`](#event-page) and [`page.on('popup')`](#event-popup) events. Provides access to the newly created page.
18971873

1898-
#### pageEvent.page()
1899-
- returns: <[Promise]<[Page]>> Promise which resolves to the created page.
1874+
#### pageEvent.page([options])
1875+
- `options` <[Object]>
1876+
- `timeout` <[number]> Maximum navigation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by using the [browserContext.setDefaultNavigationTimeout(timeout)](#browsercontextsetdefaultnavigationtimeouttimeout), [browserContext.setDefaultTimeout(timeout)](#browsercontextsetdefaulttimeouttimeout), [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout) or [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout) methods.
1877+
- `waitUntil` <"commit"|"load"|"domcontentloaded"|"networkidle0"|"networkidle2"> When to consider the page to be loaded, defaults to `load`. Events can be either:
1878+
- `'commit'` - navigation is committed, new url is displayed in the browser address bar.
1879+
- `'load'` - consider navigation to be finished when the `load` event is fired.
1880+
- `'domcontentloaded'` - consider navigation to be finished when the `DOMContentLoaded` event is fired.
1881+
- `'networkidle0'` - consider navigation to be finished when there are no more than 0 network connections for at least `500` ms.
1882+
- `'networkidle2'` - consider navigation to be finished when there are no more than 2 network connections for at least `500` ms.
1883+
- returns: <[Promise]<[Page]>> Promise which resolves to the created page once it loads, according to `waitUntil` option.
1884+
1885+
This resolves when the page reaches a required load state, `load` by default. The earliest moment that page is available is when it has committed navigation to the initial url (corresponds to `{waitUntil: 'commit'}` option). For example, when opening a popup with `window.open('http://example.com')`, this method will wait until the network request to "http://example.com" is done and its response has started loading in the popup. Passing different `waitUntil` options will also wait for the particular load state to happen, e.g. default `load` waits until the load event fires.
1886+
1887+
```js
1888+
const [, popup] = await Promise.all([
1889+
// Click opens a popup window.
1890+
page.click('button'),
1891+
// Resolves after popup has fired 'DOMContentLoaded' event.
1892+
page.waitForEvent('popup').then(event => event.page({ waitUntil: 'domcontentloaded' })),
1893+
]);
1894+
```
1895+
1896+
> **NOTE** Some pages will never fire `load` event. In this case, default `pageEvent.page()` without options will timeout - try using `pageEvent.page({ waitUntil: 'domcontentloaded' })` instead.
19001897
19011898
### class: Frame
19021899

@@ -1968,7 +1965,6 @@ An example of getting text from an iframe element:
19681965
- [frame.url()](#frameurl)
19691966
- [frame.waitFor(selectorOrFunctionOrTimeout[, options[, ...args]])](#framewaitforselectororfunctionortimeout-options-args)
19701967
- [frame.waitForFunction(pageFunction[, options[, ...args]])](#framewaitforfunctionpagefunction-options-args)
1971-
- [frame.waitForLoadState([options])](#framewaitforloadstateoptions)
19721968
- [frame.waitForNavigation([options])](#framewaitfornavigationoptions)
19731969
- [frame.waitForSelector(selector[, options])](#framewaitforselectorselector-options)
19741970
<!-- GEN:stop -->
@@ -2498,25 +2494,6 @@ const selector = '.foo';
24982494
await page.waitForFunction(selector => !!document.querySelector(selector), {}, selector);
24992495
```
25002496

2501-
#### frame.waitForLoadState([options])
2502-
- `options` <[Object]> Navigation parameters which might have the following properties:
2503-
- `timeout` <[number]> Maximum navigation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by using the [browserContext.setDefaultNavigationTimeout(timeout)](#browsercontextsetdefaultnavigationtimeouttimeout), [browserContext.setDefaultTimeout(timeout)](#browsercontextsetdefaulttimeouttimeout), [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout) or [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout) methods.
2504-
- `waitUntil` <"commit"|"load"|"domcontentloaded"|"networkidle0"|"networkidle2"> When to consider navigation succeeded, defaults to `load`. Events can be either:
2505-
- `'commit'` - navigation is committed, new url is displayed in the browser address bar.
2506-
- `'load'` - consider navigation to be finished when the `load` event is fired.
2507-
- `'domcontentloaded'` - consider navigation to be finished when the `DOMContentLoaded` event is fired.
2508-
- `'networkidle0'` - consider navigation to be finished when there are no more than 0 network connections for at least `500` ms.
2509-
- `'networkidle2'` - consider navigation to be finished when there are no more than 2 network connections for at least `500` ms.
2510-
- returns: <[Promise]> Promise which resolves when the load state has been achieved.
2511-
2512-
This resolves when the page reaches a required load state, `load` by default. The navigation can be in progress when it is called.
2513-
If navigation is already at a required state, resolves immediately.
2514-
2515-
```js
2516-
await frame.click('button'); // Click triggers navigation.
2517-
await frame.waitForLoadState(); // The promise resolves after navigation has finished.
2518-
```
2519-
25202497
#### frame.waitForNavigation([options])
25212498
- `options` <[Object]> Navigation parameters which might have the following properties:
25222499
- `timeout` <[number]> Maximum navigation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by using the [browserContext.setDefaultNavigationTimeout(timeout)](#browsercontextsetdefaultnavigationtimeouttimeout), [browserContext.setDefaultTimeout(timeout)](#browsercontextsetdefaulttimeouttimeout), [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout) or [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout) methods.

src/chromium/crBrowser.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -118,18 +118,18 @@ export class CRBrowser extends platform.EventEmitter implements Browser {
118118
try {
119119
switch (targetInfo.type) {
120120
case 'page': {
121-
const event = new PageEvent(target.pageOrError());
121+
const event = new PageEvent(context, target.pageOrError());
122122
context.emit(CommonEvents.BrowserContext.Page, event);
123123
const opener = target.opener();
124124
if (!opener)
125125
break;
126126
const openerPage = await opener.pageOrError();
127127
if (openerPage instanceof Page && !openerPage.isClosed())
128-
openerPage.emit(CommonEvents.Page.Popup, new PageEvent(target.pageOrError()));
128+
openerPage.emit(CommonEvents.Page.Popup, new PageEvent(context, target.pageOrError()));
129129
break;
130130
}
131131
case 'background_page': {
132-
const event = new PageEvent(target.pageOrError());
132+
const event = new PageEvent(context, target.pageOrError());
133133
context.emit(Events.CRBrowserContext.BackgroundPage, event);
134134
break;
135135
}

src/firefox/ffBrowser.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export class FFBrowser extends platform.EventEmitter implements Browser {
128128
const ffPage = new FFPage(session, context, opener);
129129
this._ffPages.set(targetId, ffPage);
130130

131-
const pageEvent = new PageEvent(ffPage.pageOrError());
131+
const pageEvent = new PageEvent(context, ffPage.pageOrError());
132132
context.emit(Events.BrowserContext.Page, pageEvent);
133133

134134
ffPage.pageOrError().then(() => this._firstPageCallback());

src/frames.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ export type GotoResult = {
4141
newDocumentId?: string,
4242
};
4343

44-
const kLifecycleEvents: Set<types.LifecycleEvent> = new Set(['commit', 'load', 'domcontentloaded', 'networkidle0', 'networkidle2']);
45-
4644
type ConsoleTagHandler = () => void;
4745

4846
export class FrameManager {
@@ -437,7 +435,7 @@ export class Frame {
437435
return request ? request._finalRequest._waitForResponse() : null;
438436
}
439437

440-
async waitForLoadState(options: types.NavigateOptions = {}): Promise<void> {
438+
async _waitForLoadState(options: types.NavigateOptions = {}): Promise<void> {
441439
const {timeout = this._page._timeoutSettings.navigationTimeout()} = options;
442440
const disposer = new Disposer();
443441
const error = await Promise.race([
@@ -491,7 +489,7 @@ export class Frame {
491489

492490
_waitForLifecycle(waitUntil: types.LifecycleEvent = 'load'): Disposable<Promise<void>> {
493491
let resolve: () => void;
494-
if (!kLifecycleEvents.has(waitUntil))
492+
if (!types.kLifecycleEvents.has(waitUntil))
495493
throw new Error(`Unsupported waitUntil option ${String(waitUntil)}`);
496494

497495
const checkLifecycleComplete = () => {
@@ -643,7 +641,7 @@ export class Frame {
643641
this._page._frameManager._consoleMessageTags.set(tag, () => {
644642
// Clear lifecycle right after document.open() - see 'tag' below.
645643
this._page._frameManager.clearFrameLifecycle(this);
646-
resolve(this.waitForLoadState(options));
644+
resolve(this._waitForLoadState(options));
647645
});
648646
});
649647
const contentPromise = context.evaluate((html, tag) => {

src/page.ts

+36-15
Original file line numberDiff line numberDiff line change
@@ -88,20 +88,45 @@ export type FileChooser = {
8888
};
8989

9090
export class PageEvent {
91+
private readonly _browserContext: BrowserContextBase;
9192
private readonly _pageOrError: Promise<Page | Error>;
93+
private readonly _lifecyclePromises = new Map<types.LifecycleEvent, Promise<Page | Error>>();
9294

93-
constructor(pageOrErrorPromise: Promise<Page | Error>) {
95+
constructor(browserContext: BrowserContextBase, pageOrErrorPromise: Promise<Page | Error>) {
96+
this._browserContext = browserContext;
9497
this._pageOrError = pageOrErrorPromise;
95-
}
96-
97-
async page(/* options?: frames.NavigateOptions */): Promise<Page> {
98-
const result = await this._pageOrError;
99-
if (result instanceof Page) {
100-
if (result.isClosed())
101-
throw new Error('Page has been closed.');
102-
return result;
103-
}
104-
throw result;
98+
for (const lifecycle of types.kLifecycleEvents)
99+
this._lifecyclePromises.set(lifecycle, this._createLifecyclePromise(lifecycle));
100+
}
101+
102+
async _createLifecyclePromise(lifecycle: types.LifecycleEvent): Promise<Page | Error> {
103+
const page = await this._pageOrError;
104+
if (!(page instanceof Page))
105+
return page;
106+
107+
const { dispose, value: waitForLifecycle } = page.mainFrame()._waitForLifecycle(lifecycle);
108+
const error = await Promise.race([
109+
page.mainFrame()._createFrameDestroyedPromise(),
110+
waitForLifecycle,
111+
]);
112+
dispose();
113+
if (error)
114+
return error;
115+
return page;
116+
}
117+
118+
async page(options: types.NavigateOptions = {}): Promise<Page> {
119+
const {
120+
timeout = this._browserContext._timeoutSettings.navigationTimeout(),
121+
waitUntil = 'load',
122+
} = options;
123+
const lifecyclePromise = this._lifecyclePromises.get(waitUntil);
124+
if (!lifecyclePromise)
125+
throw new Error(`Unsupported waitUntil option ${String(waitUntil)}`);
126+
const pageOrError = await helper.waitWithTimeout(lifecyclePromise, `"${waitUntil}"`, timeout);
127+
if (pageOrError instanceof Page)
128+
return pageOrError;
129+
throw pageOrError;
105130
}
106131
}
107132

@@ -311,10 +336,6 @@ export class Page extends platform.EventEmitter {
311336
return this.mainFrame().waitForNavigation(options);
312337
}
313338

314-
async waitForLoadState(options?: types.NavigateOptions): Promise<void> {
315-
return this.mainFrame().waitForLoadState(options);
316-
}
317-
318339
async waitForEvent(event: string, optionsOrPredicate: Function | (types.TimeoutOptions & { predicate?: Function }) = {}): Promise<any> {
319340
if (typeof optionsOrPredicate === 'function')
320341
optionsOrPredicate = { predicate: optionsOrPredicate };

src/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export type Polling = 'raf' | 'mutation' | number;
4646
export type WaitForFunctionOptions = TimeoutOptions & { polling?: Polling };
4747

4848
export type LifecycleEvent = 'commit' | 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2';
49+
export const kLifecycleEvents: Set<LifecycleEvent> = new Set(['commit', 'load', 'domcontentloaded', 'networkidle0', 'networkidle2']);
4950

5051
export type NavigateOptions = TimeoutOptions & {
5152
waitUntil?: LifecycleEvent,

src/webkit/wkBrowser.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ export class WKBrowser extends platform.EventEmitter implements Browser {
124124
this._firstPageCallback = undefined;
125125
}
126126

127-
const pageEvent = new PageEvent(wkPage.pageOrError());
127+
const pageEvent = new PageEvent(context, wkPage.pageOrError());
128128
context.emit(Events.BrowserContext.Page, pageEvent);
129129
if (!opener)
130130
return;

0 commit comments

Comments
 (0)