74 lines
2.7 KiB
JavaScript
74 lines
2.7 KiB
JavaScript
/**
|
|
* This file co-works with a html file and utils.js to test a promise that
|
|
* should be deferred during prerendering.
|
|
*
|
|
* Usage example:
|
|
* Suppose the html is "prerender-promise-test.html"
|
|
* On prerendering page, prerender-promise-test.html?prerendering:
|
|
* const prerenderEventCollector = new PrerenderEventCollector();
|
|
* const promise = {a promise that should be deferred during prerendering};
|
|
* prerenderEventCollector.start(promise, {promise name});
|
|
*
|
|
* On the initiator page, prerender-promise-test.html:
|
|
* execute
|
|
* `loadInitiatorPage();`
|
|
*/
|
|
|
|
// Collects events that happen relevant to a prerendering page.
|
|
// An event is added when:
|
|
// 1. start() is called.
|
|
// 2. a prerenderingchange event is dispatched on this document.
|
|
// 3. the promise passed to start() is resolved.
|
|
// 4. addEvent() is called manually.
|
|
class PrerenderEventCollector {
|
|
constructor() {
|
|
this.eventsSeen_ = [];
|
|
new PrerenderChannel('close').addEventListener('message', () => {
|
|
window.close();
|
|
});
|
|
}
|
|
|
|
// Adds an event to `eventsSeen_` along with the prerendering state of the
|
|
// page.
|
|
addEvent(eventMessage) {
|
|
this.eventsSeen_.push(
|
|
{event: eventMessage, prerendering: document.prerendering});
|
|
}
|
|
|
|
// Starts collecting events until the promise resolves. Triggers activation by
|
|
// telling the initiator page that it is ready for activation.
|
|
async start(promise, promiseName) {
|
|
assert_true(document.prerendering);
|
|
this.addEvent(`started waiting ${promiseName}`);
|
|
promise
|
|
.then(
|
|
() => {
|
|
this.addEvent(`finished waiting ${promiseName}`);
|
|
},
|
|
(error) => {
|
|
if (error instanceof Error)
|
|
error = error.name;
|
|
this.addEvent(`${promiseName} rejected: ${error}`);
|
|
})
|
|
.finally(() => {
|
|
// Used to communicate with the main test page.
|
|
const testChannel = new PrerenderChannel('test-channel');
|
|
// Send the observed events back to the main test page.
|
|
testChannel.postMessage(this.eventsSeen_);
|
|
testChannel.close();
|
|
});
|
|
document.addEventListener('prerenderingchange', () => {
|
|
this.addEvent('prerendering change');
|
|
});
|
|
|
|
// Post a task to give the implementation a chance to fail in case it
|
|
// resolves a promise without waiting for activation.
|
|
setTimeout(() => {
|
|
// Used to communicate with the initiator page.
|
|
const prerenderChannel = new PrerenderChannel('prerender-channel');
|
|
// Inform the initiator page that this page is ready to be activated.
|
|
prerenderChannel.postMessage('readyToActivate');
|
|
prerenderChannel.close();
|
|
}, 0);
|
|
}
|
|
}
|