File: deferred-promise-utils.js

package info (click to toggle)
thunderbird 1%3A128.14.0esr-1~deb13u1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 4,334,960 kB
  • sloc: cpp: 7,391,917; javascript: 5,617,271; ansic: 3,833,216; python: 1,230,742; xml: 619,690; asm: 456,020; java: 179,892; sh: 118,796; makefile: 21,906; perl: 14,825; objc: 12,399; yacc: 4,583; pascal: 2,973; lex: 1,720; ruby: 1,190; exp: 762; sql: 674; awk: 580; php: 436; lisp: 430; sed: 70; csh: 10
file content (74 lines) | stat: -rw-r--r-- 2,722 bytes parent folder | download | duplicates (18)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/**
 * 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);
  }
}