mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-06-11 01:25:53 -04:00
Immediately run deferred inline scripts after "load" is fired
Currently, any inline deferred script, e.g: <script type=module> ... </script> That happens AFTER load, never executes. Unclear how serious an issue this is, but it _does_ cause problems for some WPT tests which use document.write to inject a <script type="module">...</script> block after an iframe is loaded.
This commit is contained in:
@@ -210,7 +210,13 @@ pub fn addFromElement(self: *ScriptManager, comptime from_parser: bool, script_e
|
||||
};
|
||||
|
||||
const is_blocking = mode == .normal;
|
||||
if (is_blocking == false) {
|
||||
|
||||
// Once parsing is done, the deferred-script batch has already drained and
|
||||
// won't run again, so a non-blocking script inserted afterwards would go
|
||||
// unprocessed. Run it immediately instead. Remote scripts still need to
|
||||
// be queued so they execute when their fetch completes.
|
||||
const run_immediately = is_blocking or (self.base.static_scripts_done and remote_url == null);
|
||||
if (run_immediately == false) {
|
||||
self.base.scriptList(script).append(&script.node);
|
||||
}
|
||||
|
||||
@@ -278,7 +284,7 @@ pub fn addFromElement(self: *ScriptManager, comptime from_parser: bool, script_e
|
||||
handover = true;
|
||||
}
|
||||
|
||||
if (is_blocking == false) {
|
||||
if (run_immediately == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
37
src/browser/tests/element/html/script/postload.html
Normal file
37
src/browser/tests/element/html/script/postload.html
Normal file
@@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html>
|
||||
<head></head>
|
||||
<script src="../../../testing.js"></script>
|
||||
|
||||
<!--
|
||||
Scripts inserted *after* parsing is done (static_scripts_done == true). At that
|
||||
point the deferred-script batch has already drained and won't run again, so a
|
||||
non-blocking script must either run immediately (inline, nothing to fetch) or
|
||||
still be queued for its fetch (remote). A module script's continuation after
|
||||
the first `await` runs in this post-parse window, so we use it to do the
|
||||
insertions.
|
||||
-->
|
||||
<script id=postload type=module>
|
||||
const state = await testing.async();
|
||||
|
||||
// Inline (non-blocking, module) script must execute even though the defer
|
||||
// batch is already done.
|
||||
window.postload_inline_ran = false;
|
||||
const inline_mod = document.createElement('script');
|
||||
inline_mod.type = 'module';
|
||||
inline_mod.textContent = 'window.postload_inline_ran = true;';
|
||||
document.head.appendChild(inline_mod);
|
||||
|
||||
// Remote script must still be fetched and executed — NOT run synchronously
|
||||
// with a not-yet-loaded status (which would drop it and free it mid-fetch).
|
||||
window.loaded1 = 0;
|
||||
const remote = document.createElement('script');
|
||||
remote.src = 'dynamic1.js'; // does: loaded1 += 1
|
||||
remote.onload = () => state.resolve();
|
||||
remote.onerror = () => state.resolve(); // don't hang if it (wrongly) errors
|
||||
document.head.appendChild(remote);
|
||||
|
||||
await state.done(() => {
|
||||
testing.expectTrue(window.postload_inline_ran);
|
||||
testing.expectEqual(1, window.loaded1);
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user