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>
|