<!DOCTYPE html>
<meta charset="utf-8">
<title>Verify that promise tasks can be properly tracked.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/task-ids.js"></script>
<script>
'use strict'
promise_test((t) => {
return new Promise((resolve, reject) => {
const initialId = initializeTaskId();
const request = new XMLHttpRequest();
request.onload = t.step_func(() => {
try {
assert_equals(scheduler.taskId, initialId);
resolve();
} catch {
reject("XHR is not a descendant");
}
});
request.open("GET", "/resources/blank.html");
request.send();
});
}, "An XMLHttpRequest load event is a descendant of the requesting task");
promise_test((t) => {
return new Promise((resolve, reject) => {
const initialId = initializeTaskId();
const request = new XMLHttpRequest();
request.addEventListener('load', t.step_func(() => {
Promise.resolve().then(() => {});
}));
// This microtask checkpoint from the first listener will clear the
// continuation data in v8. Make sure the continuation data is set for the
// second listener.
request.addEventListener('load', t.step_func(() => {
try {
assert_equals(scheduler.taskId, initialId);
resolve();
} catch {
reject("XHR is not a descendant)");
}
}));
request.open("GET", "/resources/blank.html");
request.send();
});
}, "An XMLHttpRequest load event is a descendant of the requesting task (multiple listeners)");
promise_test((t) => {
return new Promise((resolve, reject) => {
const initialId = initializeTaskId();
const request = new XMLHttpRequest();
request.onreadystatechange= t.step_func(() => {
try {
assert_equals(scheduler.taskId, initialId);
} catch {
reject("XHR readystatechange is not a descendant");
}
if (request.readyState === XMLHttpRequest.DONE) {
resolve();
}
});
request.open("GET", "/resources/blank.html");
request.send();
});
}, "XMLHttpRequest readystatechange events are descendants of the requesting task");
promise_test((t) => {
return new Promise((resolve, reject) => {
let request;
let id1;
let id2;
scheduler.postTask(() => {
id1 = initializeTaskId();
request = new XMLHttpRequest();
request.onload = t.step_func(() => {
try {
assert_not_equals(scheduler.taskId, id1);
assert_equals(scheduler.taskId, id2);
resolve();
} catch {
reject("XHR is not a descendant of the correct task");
}
});
request.open("GET", "/resources/blank.html");
});
scheduler.postTask(() => {
id2 = initializeTaskId();
assert_equals(scheduler.taskId, id2);
request.send();
});
});
}, "XMLHttpRequest load event is an ancestor of send()");
promise_test((t) => {
return new Promise((resolve, reject) => {
let request;
let id1;
let id2;
scheduler.postTask(() => {
id1 = initializeTaskId();
request = new XMLHttpRequest();
request.open("GET", "/resources/blank.html");
// This runs after the send() call below.
scheduler.postTask(() => {
request.open("GET", "/resources/blank.html");
request.onload = t.step_func(() => {
try {
assert_equals(scheduler.taskId, id1);
assert_not_equals(scheduler.taskId, id2);
resolve();
} catch {
reject("XHR is not a descendant of the correct task");
}
});
request.send();
});
});
scheduler.postTask(() => {
id2 = initializeTaskId();
request.send();
});
});
}, "XMLHttpRequest load event is an ancestor of send() when reusing the object");
promise_test((t) => {
// This resolves the promise created below in an unrelated task.
let innerResolve;
(async function() {
while (!innerResolve) {
await scheduler.postTask(() => {}, {delay: 50});
}
innerResolve();
})();
return new Promise((resolve, reject) => {
// Run the rest of the test in a separate task so the polling tasks above
// won't be descendants of `initialId`.
scheduler.postTask(() => {
const initialId = initializeTaskId();
const request = new XMLHttpRequest();
request.addEventListener('load', t.step_func(() => {
assert_equals(scheduler.taskId, initialId);
Promise.resolve().then(() => {});
}));
// The microtask in the event listener above clears the continuation data
// in v8. Ensure that the right context is captured for the microtask
// below resolving the related promise in a non-ancestor task.
request.addEventListener('load', t.step_func(async () => {
await new Promise((r) => { innerResolve = r; });
try {
assert_equals(scheduler.taskId, initialId);
resolve();
} catch (e) {
reject("XHR is not a descendant");
}
}));
request.open("GET", "/resources/blank.html");
request.send();
});
});
}, "XMLHttpRequest load event is an ancestor of send() after a microtask checkpoint");
</script>