summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-job-queue/promise-job-incumbent.html
blob: af00f834c12524ae88a94ad0bdd4014e58fd4192 (plain)
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
<!DOCTYPE html>
<meta charset="utf-8">
<title>Incumbent settings object for promise jobs</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<!-- This is the entry page. -->

<iframe src="resources/promise-job-incumbent-incumbent.html"></iframe>
<iframe src="resources/promise-job-incumbent-resolver.html"></iframe>

<script>
setup({ explicit_done: true });

// postMessage should pick the incumbent page as its .source value to set on the MessageEvent, even
// inside promise jobs.
const expectedURL = (new URL("resources/promise-job-incumbent-incumbent.html", location.href)).href;

let testId = 0;

window.onload = () => {
  const relevantWindow = frames[0].document.querySelector("#r").contentWindow;
  const runInResolver = frames[1].runWhatYouGiveMe;

  function setupTest(t) {
    ++testId;
    const thisTestId = testId;

    relevantWindow.addEventListener("messagereceived", t.step_func(e => {
      const [receivedTestId, receivedSourceURL] = e.detail;

      if (receivedTestId !== thisTestId) {
        return;
      }

      assert_equals(receivedSourceURL, expectedURL);
      t.done();
    }));

    return thisTestId;
  }

  async_test(t => {
    const thisTestId = setupTest(t);

    frames[0].runWindowPostMessageVeryIndirectly(thisTestId, "*");
  }, "Sanity check: this all works as expected with no promises involved");

  async_test(t => {
    const thisTestId = setupTest(t);

    // No t.step_func because that could change the realms
    Promise.resolve().then(() => {
      frames[0].runWindowPostMessageVeryIndirectly(thisTestId, "*");
    });
  }, "Fulfillment handler on fulfilled promise");

  async_test(t => {
    const thisTestId = setupTest(t);

    const p = Promise.resolve();
    frames[0].runWindowPostMessageVeryIndirectlyWithNoUserCode(p, "then", thisTestId, "*");
  }, "Fulfillment handler on fulfilled promise, using backup incumbent settings object stack");

  async_test(t => {
    const thisTestId = setupTest(t);

    // No t.step_func because that could change the realms
    Promise.reject().catch(() => {
      frames[0].runWindowPostMessageVeryIndirectly(thisTestId, "*");
    });
  }, "Rejection handler on rejected promise");

  async_test(t => {
    const thisTestId = setupTest(t);

    const p = Promise.reject();
    frames[0].runWindowPostMessageVeryIndirectlyWithNoUserCode(p, "catch", thisTestId, "*");
  }, "Rejection handler on rejected promise, using backup incumbent settings object stack");

  // The following tests test that we derive the incumbent settings object at promise-job time from
  // the incumbent realm at the time the handler was added, not at the time the resolve()/reject()
  // was done. See https://github.com/whatwg/html/issues/5213 for the spec side of this issue.

  async_test(t => {
    const thisTestId = setupTest(t);

    let resolve;
    const p = new Promise(r => { resolve = r; });

    // No t.step_func because that could change the realms
    p.then(() => {
      frames[0].runWindowPostMessageVeryIndirectly(thisTestId, "*");
    });

    t.step_timeout(() => {
      runInResolver(resolve);
    }, 0);
  }, "Fulfillment handler on pending-then-fulfilled promise");

  async_test(t => {
    const thisTestId = setupTest(t);

    let resolve;
    const p = new Promise(r => { resolve = r; });

    frames[0].runWindowPostMessageVeryIndirectlyWithNoUserCode(p, "then", thisTestId, "*");

    t.step_timeout(() => {
      runInResolver(resolve);
    }, 0);
  }, "Fulfillment handler on pending-then-fulfilled promise, using backup incumbent settings object stack");

  async_test(t => {
    const thisTestId = setupTest(t);

    let reject;
    const p = new Promise((_, r) => { reject = r; });

    // No t.step_func because that could change the realms
    p.catch(() => {
      frames[0].runWindowPostMessageVeryIndirectly(thisTestId, "*");
    });

    t.step_timeout(() => {
      runInResolver(reject);
    }, 0);
  }, "Rejection handler on pending-then-rejected promise");

  async_test(t => {
    const thisTestId = setupTest(t);

    let reject;
    const p = new Promise((_, r) => { reject = r; });

    frames[0].runWindowPostMessageVeryIndirectlyWithNoUserCode(p, "catch", thisTestId, "*");

    t.step_timeout(() => {
      runInResolver(reject);
    }, 0);
  }, "Rejection handler on pending-then-rejected promise, using backup incumbent settings object stack");

  async_test(t => {
    const thisTestId = setupTest(t);

    const thenable = {
      // No t.step_func because that could change the realms
      then(f) {
        frames[0].runWindowPostMessageVeryIndirectly(thisTestId, "*");
      }
    };

    Promise.resolve(thenable);
  }, "Thenable resolution");

  async_test(t => {
    const thisTestId = setupTest(t);

    frames[0].resolveThenableThatRunsWindowPostMessageVeryIndirectlyWithNoUserCode(testId, "*", []);
  }, "Thenable resolution, using backup incumbent settings object stack");

  done();
};
</script>