Top-level await blocking test

tags:: sketchbook
date:: Apr 29th, 2023

You have 30 seconds to read this. It will self-destruct. I’m not kidding; see below for why.

Top-level await is available inside <script type="module">. Aren’t those scripts synchronous? If so, does that top-level await block the entire document from being parsed?

Here’s the code currently executing:

const log = document.getElementById("log");
log.textContent += "Loaded. Waiting for 2 seconds...\n";

await new Promise(resolve => setTimeout(resolve, 5000))

log.textContent += "Done\n";

There’s another <script type="module"> after it:

const log = document.getElementById("log");
log.textContent += "The next JS module executed\n";

This is some content after the module. If this doesn’t appear for 5 seconds, that means the JS code blocked the entire HTML from even being parsed.

Hooray! It looks like it doesn’t block it.

Hmmm… strange. It looks like the HTML is parsed afterwards. I also added another JS module afterwards and it executed. So the module with top-level await does not block anything. <script type="module"> defaults to async execution.

However, if I use document.write inside of it, it blows away the whole page! Count down from 30 seconds…

await new Promise(resolve => setTimeout(resolve, 30000))

document.write('This message has self-destructed.')

Strangely, if you use document.write in a <script type="module"> but don’t use top-level await, document.write seems to do nothing at all!

Update: Actually, this is expected behavior. I forgot that when you do a document.write in JavaScript when you aren’t synchronously executing in the HTML parsing phase, it just overwrites the entire page. So this behavior makes sense. It’s a little surprising the document.write doesn’t do anything in a <script type="module"> though.