LibWeb: Perform a microtask checkpoint - VERIFY after reentrancy return

The HTML event loop spec explicitly provides guidance for reentrancy in
the "perform a microtask checkpoint" algorithm, so we cannot VERIFY
for empty execution context before this early exit (as much as we'd
like to).

https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint

See the microtask-checkpoint-reentrancy-via-responsexml-script test for
an example of how this can happen from user scripts.
This commit is contained in:
Jonathan Gamble 2026-02-16 18:41:55 -06:00 committed by Shannon Booth
parent a19db375b5
commit d065f6bf00
3 changed files with 29 additions and 4 deletions

View file

@ -610,14 +610,14 @@ void EventLoop::perform_a_microtask_checkpoint()
if (execution_paused())
return;
// NOTE: This assertion is per requirement 9.5 of the ECMA-262 spec, see: https://tc39.es/ecma262/#sec-jobs
// > At some future point in time, when there is no running context in the agent for which the job is scheduled and that agent's execution context stack is empty...
VERIFY(vm().execution_context_stack().is_empty());
// 1. If the event loop's performing a microtask checkpoint is true, then return.
if (m_performing_a_microtask_checkpoint)
return;
// NOTE: This assertion is per requirement 9.5 of the ECMA-262 spec, see: https://tc39.es/ecma262/#sec-jobs
// > At some future point in time, when there is no running context in the agent for which the job is scheduled and that agent's execution context stack is empty...
VERIFY(vm().execution_context_stack().is_empty());
// 2. Set the event loop's performing a microtask checkpoint to true.
m_performing_a_microtask_checkpoint = true;

View file

@ -0,0 +1,24 @@
<!DOCTYPE html>
<script src="../include.js"></script>
<script>
asyncTest(done => {
const xhr = new XMLHttpRequest();
xhr.responseType = "document";
xhr.open(
"GET",
"data:text/xml,<root xmlns:h='http://www.w3.org/1999/xhtml'><h:script>void 0</h:script></root>",
true
);
xhr.addEventListener("load", () => {
queueMicrotask(() => {
void xhr.responseXML;
println("PASS (didn't crash)");
done();
});
});
xhr.send();
});
</script>